all: non_local_jump_test.exe
-non_local_jump_test.exe: non_local_jump_test.adb non_local_jump.adb non_local_jump.ads eat_20.c eat_20.h
- mgcc -c -g eat_20.c
- mgnatmake -o $@ $<
+non_local_jump_test.exe: non_local_jump_test.adb
+ mgnatmake -Imarte_src_dirs -o $@ $<
clean:
+++ /dev/null
-void eat_20() {
- int i;
- for (i=0; i<200000000; i++){
- i++;
- i--;
- }
-}
+++ /dev/null
-void eat_20();
+++ /dev/null
-/*----------------------------------------------------------------------------\r
- *------------------------ M a R T E O S -------------------------\r
- *----------------------------------------------------------------------------\r
- * {MARTE_VERSION}\r
- *\r
- * 'm a r t e _ n o n _ l o c a l _ j m p'\r
- *\r
- * H\r
- *\r
- * File 'marte_non_local_jmp.h' By MAR.\r
- *\r
- * Non-local jumps for preempted tasks.\r
- * Functionality implemented in 'non_local_jump.ad[ab]'.\r
- *\r
- * {MARTE_COPYRIGHT}\r
- *\r
- *---------------------------------------------------------------------------*/\r
-/* {<MAR}\r
- *\r
- * 02-08-07: primera versiĆ³n\r
- *\r
- * {MAR>} -------------------------------------------------------------------*/\r
-\r
-#ifndef _MARTE_NON_LOCAL_JMP_H_\r
-#define _MARTE_NON_LOCAL_JMP_H_\r
-\r
-//#include <sys/cpp_macros.h>\r
-#include <sys/types.h>\r
-\r
-//CPP_BEGIN_DECLS\r
-\r
-// GNAT 2005: typedef struct { int b[108/4]; } marte_nonlocaljmp_context_t;\r
-\r
-typedef struct { int b[156/4]; } marte_nonlocaljmp_context_t;\r
-\r
-/*-----------------------------------\r
- *-- marte_nonlocaljmp_savecontext --\r
- *-----------------------------------*/\r
-/*\r
- * Context stores the information required to modify the stack of a\r
- * preempted task with 'restorecontext'.\r
- *\r
- * This function stores in 'context' the registers and its stack frame. This\r
- * information can be used for 'restorecontext' to change the stack of the\r
- * task (when it is preempted) so that when it is scheduled again it returns\r
- * to the end of this function\r
- */\r
-void marte_nonlocaljmp_savecontext\r
- (marte_nonlocaljmp_context_t * context);\r
-\r
-/*----------------------------------\r
- *-- marte_nonlocaljmp_afterjmp --\r
- *----------------------------------*/\r
-/*\r
- * To be invoked after 'Save_Context'. If invoked after a direct invocation\r
- * to 'Save_Context', 'After_Jump' shall return 0. If invoked after\r
- * returning from 'Save_Context' due to a call to 'Restore_Context',\r
- * 'After_Jump' shall return 1.\r
- */\r
- int marte_nonlocaljmp_afterjmp(const marte_nonlocaljmp_context_t * context);\r
-\r
-/*--------------------------------------\r
- *-- marte_nonlocaljmp_restorecontext --\r
- *--------------------------------------*/\r
-/*\r
- * This procedure changes the return context of a preempted task.\r
- *\r
- * | | | |\r
- * TCB_Ac.Stack_Ptr->| Regs | | |\r
- * | | | |\r
- * ... ...\r
- * | | | ret |<-TCB_Ac.Stack_Ptr\r
- * | | | ebp |\r
- * | |<-Context.Esp->| SC* |\r
- * | | | SC* |\r
- * | | | SC* |\r
- * | | | |\r
- * before after\r
- * SC*: stack frame of 'Save_Context'.\r
- *\r
- * The next time the task is scheduled will execute the final part of\r
- * Save_Context.\r
- *\r
- * The full process is the following: 'Save_Context' stores the registers\r
- * and its stack frame in 'Jmp_Context'. 'Restore_Context' restores that\r
- * context placing the stored frame in the same position of the stack it was\r
- * originally. Over this frame it is placed the value of the ebp register\r
- * and the address of label "1:" in 'Save_Context'.\r
- * When the task is scheduled again, the first instruction it executes is\r
- * "ret" in 'Processor_Registers.Context_Switch' and then the address of\r
- * label "1:" in 'Save_Context' is popped from the stack. Once in\r
- * 'Save_Context', the ebp register is also popped and, with this\r
- * instruction, the registers and stack are in the same situation it was the\r
- * time that the contexts was stored, and then the final part of\r
- * 'Save_Context' can be executed successfully.\r
- */\r
-void marte_nonlocaljmp_restorecontext\r
- (pthread_t th,\r
- marte_nonlocaljmp_context_t * context);\r
-\r
-//CPP_END_DECLS\r
-\r
-#endif // _MARTE_NON_LOCAL_JMP_H_\r
+++ /dev/null
-------------------------------------------------------------------------------
--- ------------------ M a R T E O S ------------------- --
-------------------------------------------------------------------------------
--- {MARTE_VERSION}
---
--- 'N o n _ L o c a l _ J u m p'
---
--- Body
---
--- File 'non_local_jump.adb' By MAR
---
--- Non-local jumps for preempted tasks.
---
--- IMPORTANT: it must be compiled without any optimization!!
---
--- {MARTE_COPYRIGHT}
---
-------------------------------------------------------------------------------
--- {<MAR}
---
--- 02-08-07:version operativa.
---
--- {MAR>} -------------------------------------------------------------------
-with System.Machine_Code; use System.Machine_Code;
-with Ada.Unchecked_Conversion;
-with Marte.Hal;
-
-package body Non_Local_Jump is
- use Marte.Integer_Types;
- use System;
-
- pragma Optimize (Off);
-
- -------------------
- -- Save_Context --
- -------------------
- --
- -- Context stores the information required to modify the stack of a
- -- preempted task with 'Change_Return_Context_Of_Preempted_Task'.
- --
- --
- procedure Save_Context (Context : access Jmp_Context) is
- pragma Optimize (Off);
-
- function To_Save_Context_Stack_Ac is
- new Ada.Unchecked_Conversion (Unsigned_32, Save_Context_Stack_Ac);
- begin
- -- Store registers
- Asm ("pushl %%eax;" &
- "pushl %%ebp;" &
- "pushl %%edi;" &
- "pushl %%esi;" &
- "pushl %%edx;" &
- "pushl %%ecx;" &
- "pushl %%ebx;" &
- "pushl $1f;",
- No_Output_Operands, No_Input_Operands, "", True);
-
- Asm ("popl %0 ;" &
- "popl %1 ;" &
- "popl %2 ;" &
- "popl %3 ;" &
- "popl %4 ;" &
- "popl %5 ;" &
- "popl %6 ;" &
- "popl %7 ;",
- (Address'Asm_Output ("=g", Context.Return_Address),
- Unsigned_32'Asm_Output ("=g", Context.Ebx),
- Unsigned_32'Asm_Output ("=g", Context.Ecx),
- Unsigned_32'Asm_Output ("=g", Context.Edx),
- Unsigned_32'Asm_Output ("=g", Context.Esi),
- Unsigned_32'Asm_Output ("=g", Context.Edi),
- Unsigned_32'Asm_Output ("=g", Context.Ebp),
- Unsigned_32'Asm_Output ("=g", Context.Eax)),
- No_Input_Operands, "", True);
-
- -- Mark context has been used in a direct invocation of 'Save_Context'
- pragma Validity_Checks (Off);
- Context.After_Jmp := 0;
- pragma Validity_Checks (On);
-
- -- Store esp
- Asm ("movl %%esp, %0;",
- Unsigned_32'Asm_Output ("=g", Context.Esp),
- No_Input_Operands, "", True);
-
- -- Save stack
- pragma Validity_Checks (Off);
- Context.Context_Stack := To_Save_Context_Stack_Ac (Context.Esp).all;
- pragma Validity_Checks (On);
-
- -- Push ebp to be restored after label "1:"
- Asm ("pushl %%ebp;",
- No_Output_Operands, No_Input_Operands, "", True);
-
- -- return address where the task returns after it is scheduled again. It
- -- jumps here from the 'ret' instruction in
- -- 'Processor_Registers.Context_Switch'.
- Asm ("1: popl %%ebp;",
- No_Output_Operands,
- No_Input_Operands, "", True);
- Marte.Hal.Enable_Interrupts;
- end Save_Context;
-
- ------------------
- -- After_Jump --
- ------------------
- --
- -- To be invoked after 'Save_Context'. If invoked after a direct invocation
- -- to 'Save_Context', 'After_Jump' shall return False. If invoked after
- -- returning from 'Save_Context' due to a call to 'Restore_Context',
- -- 'After_Jump' shall return True.
- function After_Jump (Context : access Jmp_Context) return Unsigned_32 is
- begin
- return Context.After_Jmp;
- end After_Jump;
-
- ---------------------
- -- Restore_Context --
- ---------------------
- --
- -- This procedure changes the return context of a preempted task.
- --
- -- | | | |
- -- TCB_Ac.Stack_Ptr->| Regs | | |
- -- | | | |
- -- ... ...
- -- | | | |
- -- | | |Context|<-TCB_Ac.Stack_Ptr
- -- | |<-Context.Esp->| |
- -- | | | |
- -- | | | |
- -- | | | |
- -- before after
- -- The next time the task is scheduled will execute the final part of
- -- Save_Context.
- procedure Restore_Context (TCB_Ac : System.Address;
- Context : access Jmp_Context) is
-
- -- TCB_Ac points to the TCB of preempted task (a Kernel.TCB). The first
- -- 8 bytes are the tag and the top of the stack of preempted task.
- type Beginning_Of_TCB is record
- Tag : Unsigned_32;
- Top_Of_Stack : Preempted_Task_Restore_Context_Stack_Ac;
- end record;
- type Beginning_Of_TCB_Ac is access Beginning_Of_TCB;
-
- function UC is
- new Ada.Unchecked_Conversion (System.Address, Beginning_Of_TCB_Ac);
- function UC is
- new Ada.Unchecked_Conversion (Unsigned_32,
- Preempted_Task_Restore_Context_Stack_Ac);
- begin
-
- -- Set top of stack of the task to its new value
- UC (TCB_Ac).Top_Of_Stack :=
- UC (Context.Esp - Context.Return_Address'Size / 8
- - Context.Ebp'Size / 8);
-
- -- Create new return context
- UC (TCB_Ac).Top_Of_Stack.all :=
- (Return_Address => Context.Return_Address,
- Ebp => Context.Ebp,
- Context_Stack => Context.Context_Stack);
-
- -- The context has been used to perform a non-local jump
- Context.After_Jmp := 1;
- end Restore_Context;
-
-end Non_Local_Jump;
+++ /dev/null
-------------------------------------------------------------------------------
--- ------------------ M a R T E O S ------------------- --
-------------------------------------------------------------------------------
--- {MARTE_VERSION}
---
--- 'N o n _ L o c a l _ J u m p'
---
--- Spec
---
--- File 'non_local_jump.ads' By MAR
---
--- Non-local jumps for preempted tasks.
---
--- IMPORTANT: it must be compiled without any optimization!!
---
--- {MARTE_COPYRIGHT}
---
-------------------------------------------------------------------------------
--- {<MAR}
---
--- 02-08-07:version operativa.
---
--- {MAR>} -------------------------------------------------------------------
-with System;
-with Marte.Integer_Types;
-
-package Non_Local_Jump is
- pragma Optimize (Off);
-
- type Jmp_Context is private;
-
- -------------------
- -- Save_Context --
- -------------------
- --
- -- Context stores the information required to modify the stack of a
- -- preempted task with 'Change_Return_Context_Of_Preempted_Task'.
- --
- -- This function stores in 'Context' the registers and its stack frame. This
- -- information can be used for 'Restore_Context' to change the stack of the
- -- task (when it is preempted) so that when it is scheduled again it returns
- -- to the end of this function
- --
- procedure Save_Context (Context : access Jmp_Context);
- pragma Export (C, Save_Context, "marte_nonlocaljmp_savecontext");
-
- ------------------
- -- After_Jump --
- ------------------
- --
- -- To be invoked after 'Save_Context'. If invoked after a direct invocation
- -- to 'Save_Context', 'After_Jump' shall return 0 (False). If invoked after
- -- returning from 'Save_Context' due to a call to 'Restore_Context',
- -- 'After_Jump' shall return 1 (True).
- function After_Jump (Context : access Jmp_Context)
- return Marte.Integer_Types.Unsigned_32;
- pragma Export (C, After_Jump, "marte_nonlocaljmp_afterjmp");
-
- ---------------------
- -- Restore_Context --
- ---------------------
- --
- -- This procedure changes the return context of a preempted task.
- --
- -- | | | |
- -- TCB_Ac.Stack_Ptr->| Regs | | |
- -- | | | |
- -- ... ...
- -- | | | ret |<-TCB_Ac.Stack_Ptr
- -- | | | ebp |
- -- | |<-Context.Esp->| SC* |
- -- | | | SC* |
- -- | | | SC* |
- -- | | | |
- -- before after
- -- SC*: stack frame of 'Save_Context'.
- --
- -- The next time the task is scheduled will execute the final part of
- -- Save_Context.
- --
- -- The full process is the following: 'Save_Context' stores the registers
- -- and its stack frame in 'Jmp_Context'. 'Restore_Context' restores that
- -- context placing the stored frame in the same position of the stack it was
- -- originally. Over this frame it is placed the value of the ebp register
- -- and the address of label "1:" in 'Save_Context'.
- -- When the task is scheduled again, the first instruction it executes is
- -- "ret" in 'Processor_Registers.Context_Switch' and then the address of
- -- label "1:" in 'Save_Context' is popped from the stack. Once in
- -- 'Save_Context', the ebp register is also popped and, with this
- -- instruction, the registers and stack are in the same situation it was the
- -- time that the contexts was stored, and then the final part of
- -- 'Save_Context' can be executed successfully.
- procedure Restore_Context (TCB_Ac : System.Address;
- Context : access Jmp_Context);
- pragma Export (C, Restore_Context, "marte_nonlocaljmp_restorecontext");
-
-private
-
- type Save_Context_Stack is array (1 .. 29) of -- 17->2005, 29->2007
- Marte.Integer_Types.Unsigned_32;
- type Save_Context_Stack_Ac is access Save_Context_Stack;
- -- Stack of 'Save_Context' funcion. The frame created by 'Save_Context' is
- -- 16/28 integers long when no optimization is used for this function. The
- -- total size is 17/29 because ebp register is also stored in the stack
-
- -- A change in this record could affect the type
- -- 'marte_nonlocaljmp_context_t' defined in
- -- 'x86_arch/include/misc/marte_non_local_jmp.h'
- type Jmp_Context is record
- Return_Address : System.Address;
- -- The address of label "1:" inside 'Save_Context'. The task jumps to
- -- this instruction from the 'ret' instruction in
- -- 'Processor_Registers.Context_Switch'.
-
- Ebx : Marte.Integer_Types.Unsigned_32;
- Ecx : Marte.Integer_Types.Unsigned_32;
- Edx : Marte.Integer_Types.Unsigned_32;
- Esi : Marte.Integer_Types.Unsigned_32;
- Edi : Marte.Integer_Types.Unsigned_32;
- Ebp : Marte.Integer_Types.Unsigned_32;
- Eax : Marte.Integer_Types.Unsigned_32;
-
- Esp : Marte.Integer_Types.Unsigned_32; -- top of stack
-
- After_Jmp : Marte.Integer_Types.Unsigned_32;
- -- 0 (False) after a direct invocation to 'Save_Context'. 1 (True) if
- -- 'Restore_Context' has been invoked.
-
- Context_Stack : Save_Context_Stack;
- -- Stack frame of 'Save_Context' funcion
-
- end record;
- pragma Volatile (Jmp_Context);
- type Jmp_Context_Ac is access Jmp_Context;
-
- type Preempted_Task_Restore_Context_Stack is record
- Return_Address : System.Address;
- Ebp : Marte.Integer_Types.Unsigned_32;
- Context_Stack : Save_Context_Stack;
- end record;
- type Preempted_Task_Restore_Context_Stack_Ac is
- access Preempted_Task_Restore_Context_Stack;
-
-end Non_Local_Jump;
--\r
-- {MAR>} -------------------------------------------------------------------\r
pragma Task_Dispatching_Policy (FIFO_Within_Priorities);\r
-with MaRTE_OS;\r
with Text_IO; use Text_IO;\r
with Ada.Unchecked_Conversion;\r
with System;\r
with Marte.Integer_Types; use Marte.Integer_Types;\r
--- with Processor_Registers;\r
+with Marte.HAL.Processor_Registers;\r
with Non_Local_Jump;\r
with System.Machine_Code; use System.Machine_Code;\r
+with Execution_Load;\r
\r
procedure Non_Local_Jump_Test is\r
\r
- pragma Linker_Options("eat_20.o");\r
+ --pragma Linker_Options("eat_20.o");\r
\r
- procedure Eat_20;\r
- pragma Import (C, Eat_20, "eat_20");\r
+ --procedure Eat_20;\r
+ --pragma Import (C, Eat_20, "eat_20");\r
\r
pragma Priority (10);\r
\r
loop\r
\r
Put_Line (Integer'Image (C));\r
- Eat_20;\r
+ Execution_Load.Eat (20.0);\r
--for I in 1 .. 20_000_000 loop\r
-- null;\r
--end loop;\r
if PR.After_Jump (Jmp_Buff'Access) = 1 then\r
Put_Line ("---After Jump---");\r
else\r
+ Put_Line ("---Not After Jump 1---");\r
Por_Fastidiar1 (Cont);\r
- Put_Line ("---Not After Jump---");\r
+ Put_Line ("---Not After Jump 2---");\r
end if;\r
Cont := Cont + 1;\r
Put_Line(" Cont:" & Integer'Image (Cont));\r