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;
28 package body Non_Local_Jump is
29 use Marte.Integer_Types;
32 pragma Optimize (Off);
38 -- Context stores the information required to modify the stack of a
39 -- preempted task with 'Change_Return_Context_Of_Preempted_Task'.
42 procedure Save_Context (Context : access Jmp_Context) is
43 pragma Optimize (Off);
45 function To_Save_Context_Stack_Ac is
46 new Ada.Unchecked_Conversion (Unsigned_32, Save_Context_Stack_Ac);
57 No_Output_Operands, No_Input_Operands, "", True);
67 (Address'Asm_Output ("=g", Context.Return_Address),
68 Unsigned_32'Asm_Output ("=g", Context.Ebx),
69 Unsigned_32'Asm_Output ("=g", Context.Ecx),
70 Unsigned_32'Asm_Output ("=g", Context.Edx),
71 Unsigned_32'Asm_Output ("=g", Context.Esi),
72 Unsigned_32'Asm_Output ("=g", Context.Edi),
73 Unsigned_32'Asm_Output ("=g", Context.Ebp),
74 Unsigned_32'Asm_Output ("=g", Context.Eax)),
75 No_Input_Operands, "", True);
77 -- Mark context has been used in a direct invocation of 'Save_Context'
78 pragma Validity_Checks (Off);
79 Context.After_Jmp := 0;
80 pragma Validity_Checks (On);
83 Asm ("movl %%esp, %0;",
84 Unsigned_32'Asm_Output ("=g", Context.Esp),
85 No_Input_Operands, "", True);
88 pragma Validity_Checks (Off);
89 Context.Context_Stack := To_Save_Context_Stack_Ac (Context.Esp).all;
90 pragma Validity_Checks (On);
92 -- Push ebp to be restored after label "1:"
94 No_Output_Operands, No_Input_Operands, "", True);
96 -- return address where the task returns after it is scheduled again. It
97 -- jumps here from the 'ret' instruction in
98 -- 'Processor_Registers.Context_Switch'.
99 Asm ("1: popl %%ebp;",
101 No_Input_Operands, "", True);
102 Marte.Hal.Enable_Interrupts;
109 -- To be invoked after 'Save_Context'. If invoked after a direct invocation
110 -- to 'Save_Context', 'After_Jump' shall return False. If invoked after
111 -- returning from 'Save_Context' due to a call to 'Restore_Context',
112 -- 'After_Jump' shall return True.
113 function After_Jump (Context : access Jmp_Context) return Unsigned_32 is
115 return Context.After_Jmp;
118 ---------------------
119 -- Restore_Context --
120 ---------------------
122 -- This procedure changes the return context of a preempted task.
125 -- TCB_Ac.Stack_Ptr->| Regs | | |
129 -- | | |Context|<-TCB_Ac.Stack_Ptr
130 -- | |<-Context.Esp->| |
135 -- The next time the task is scheduled will execute the final part of
137 procedure Restore_Context (TCB_Ac : System.Address;
138 Context : access Jmp_Context) is
140 -- TCB_Ac points to the TCB of preempted task (a Kernel.TCB). The first
141 -- 8 bytes are the tag and the top of the stack of preempted task.
142 type Beginning_Of_TCB is record
144 Top_Of_Stack : Preempted_Task_Restore_Context_Stack_Ac;
146 type Beginning_Of_TCB_Ac is access Beginning_Of_TCB;
149 new Ada.Unchecked_Conversion (System.Address, Beginning_Of_TCB_Ac);
151 new Ada.Unchecked_Conversion (Unsigned_32,
152 Preempted_Task_Restore_Context_Stack_Ac);
155 -- Set top of stack of the task to its new value
156 UC (TCB_Ac).Top_Of_Stack :=
157 UC (Context.Esp - Context.Return_Address'Size / 8
158 - Context.Ebp'Size / 8);
160 -- Create new return context
161 UC (TCB_Ac).Top_Of_Stack.all :=
162 (Return_Address => Context.Return_Address,
164 Context_Stack => Context.Context_Stack);
166 -- The context has been used to perform a non-local jump
167 Context.After_Jmp := 1;