1 ------------------------------------------------------------------------------
2 -- ------------------ M a R T E O S ------------------- --
3 ------------------------------------------------------------------------------
6 -- 'N o n _ L o c a l _ J u m p'
10 -- File 'non_local_jump.adb' By MAR
12 -- Non-local jumps for preempted tasks.
14 -- IMPORTANT: it must be compiled without any optimization!!
18 ------------------------------------------------------------------------------
21 -- 02-08-07:version operativa.
23 -- {MAR>} -------------------------------------------------------------------
24 with System.Machine_Code; use System.Machine_Code;
25 with Ada.Unchecked_Conversion;
27 package body Non_Local_Jump is
28 use Basic_Integer_Types;
31 pragma Optimize (Off);
37 -- Context stores the information required to modify the stack of a
38 -- preempted task with 'Change_Return_Context_Of_Preempted_Task'.
41 procedure Save_Context (Context : access Jmp_Context) is
42 pragma Optimize (Off);
44 function To_Save_Context_Stack_Ac is
45 new Ada.Unchecked_Conversion (Unsigned_32, Save_Context_Stack_Ac);
56 No_Output_Operands, No_Input_Operands, "", True);
66 (Address'Asm_Output ("=g", Context.Return_Address),
67 Unsigned_32'Asm_Output ("=g", Context.Ebx),
68 Unsigned_32'Asm_Output ("=g", Context.Ecx),
69 Unsigned_32'Asm_Output ("=g", Context.Edx),
70 Unsigned_32'Asm_Output ("=g", Context.Esi),
71 Unsigned_32'Asm_Output ("=g", Context.Edi),
72 Unsigned_32'Asm_Output ("=g", Context.Ebp),
73 Unsigned_32'Asm_Output ("=g", Context.Eax)),
74 No_Input_Operands, "", True);
76 -- Mark context has been used in a direct invocation of 'Save_Context'
77 pragma Validity_Checks (Off);
78 Context.After_Jmp := 0;
79 pragma Validity_Checks (On);
82 Asm ("movl %%esp, %0;",
83 Unsigned_32'Asm_Output ("=g", Context.Esp),
84 No_Input_Operands, "", True);
87 pragma Validity_Checks (Off);
88 Context.Context_Stack := To_Save_Context_Stack_Ac (Context.Esp).all;
89 pragma Validity_Checks (On);
91 -- Push ebp to be restored after label "1:"
93 No_Output_Operands, No_Input_Operands, "", True);
95 -- return address where the task returns after it is scheduled again. It
96 -- jumps here from the 'ret' instruction in
97 -- 'Processor_Registers.Context_Switch'.
98 Asm ("1: popl %%ebp;",
100 No_Input_Operands, "", True);
107 -- To be invoked after 'Save_Context'. If invoked after a direct invocation
108 -- to 'Save_Context', 'After_Jump' shall return False. If invoked after
109 -- returning from 'Save_Context' due to a call to 'Restore_Context',
110 -- 'After_Jump' shall return True.
111 function After_Jump (Context : access Jmp_Context) return Unsigned_32 is
113 return Context.After_Jmp;
116 ---------------------
117 -- Restore_Context --
118 ---------------------
120 -- This procedure changes the return context of a preempted task.
123 -- TCB_Ac.Stack_Ptr->| Regs | | |
127 -- | | |Context|<-TCB_Ac.Stack_Ptr
128 -- | |<-Context.Esp->| |
133 -- The next time the task is scheduled will execute the final part of
135 procedure Restore_Context (TCB_Ac : System.Address;
136 Context : access Jmp_Context) is
138 -- TCB_Ac points to the TCB of preempted task (a Kernel.TCB). The first
139 -- 8 bytes are the tag and the top of the stack of preempted task.
140 type Beginning_Of_TCB is record
142 Top_Of_Stack : Preempted_Task_Restore_Context_Stack_Ac;
144 type Beginning_Of_TCB_Ac is access Beginning_Of_TCB;
147 new Ada.Unchecked_Conversion (System.Address, Beginning_Of_TCB_Ac);
149 new Ada.Unchecked_Conversion (Unsigned_32,
150 Preempted_Task_Restore_Context_Stack_Ac);
153 -- Set top of stack of the task to its new value
154 UC (TCB_Ac).Top_Of_Stack :=
155 UC (Context.Esp - Context.Return_Address'Size / 8
156 - Context.Ebp'Size / 8);
158 -- Create new return context
159 UC (TCB_Ac).Top_Of_Stack.all :=
160 (Return_Address => Context.Return_Address,
162 Context_Stack => Context.Context_Stack);
164 -- The context has been used to perform a non-local jump
165 Context.After_Jmp := 1;