]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - marte_non_local_jump/non_local_jump.adb
Changed the comments on the long jump functions to better describe their
[frescor/fosa.git] / marte_non_local_jump / non_local_jump.adb
1 ------------------------------------------------------------------------------
2 --  ------------------         M a R T E   O S         -------------------  --
3 ------------------------------------------------------------------------------
4 --                                                             {MARTE_VERSION}
5 --
6 --                      'N o n _ L o c a l _ J u m p'
7 --
8 --                                  Body
9 --
10 --  File 'non_local_jump.adb'                                          By MAR
11 --
12 --  Non-local jumps for preempted tasks.
13 --
14 --  IMPORTANT: it must be compiled without any optimization!!
15 --
16 --  {MARTE_COPYRIGHT}
17 --
18 ------------------------------------------------------------------------------
19 --  {<MAR}
20 --
21 --  02-08-07:version operativa.
22 --
23 --  {MAR>} -------------------------------------------------------------------
24 with System.Machine_Code; use System.Machine_Code;
25 with Ada.Unchecked_Conversion;
26
27 package body Non_Local_Jump is
28    use Basic_Integer_Types;
29    use System;
30
31    pragma Optimize (Off);
32
33    -------------------
34    -- Save_Context --
35    -------------------
36    --
37    --  Context stores the information required to modify the stack of a
38    --  preempted task with 'Change_Return_Context_Of_Preempted_Task'.
39    --
40    --
41    procedure Save_Context (Context : access Jmp_Context) is
42       pragma Optimize (Off);
43
44       function To_Save_Context_Stack_Ac is
45         new Ada.Unchecked_Conversion (Unsigned_32, Save_Context_Stack_Ac);
46    begin
47       --  Store registers
48       Asm ("pushl %%eax;" &
49            "pushl %%ebp;" &
50            "pushl %%edi;" &
51            "pushl %%esi;" &
52            "pushl %%edx;" &
53            "pushl %%ecx;" &
54            "pushl %%ebx;"  &
55            "pushl $1f;",
56            No_Output_Operands, No_Input_Operands, "", True);
57
58       Asm ("popl %0 ;" &
59         "popl %1 ;" &
60         "popl %2 ;" &
61         "popl %3 ;" &
62         "popl %4 ;" &
63         "popl %5 ;" &
64         "popl %6 ;" &
65         "popl %7 ;",
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);
75
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);
80
81       --  Store esp
82       Asm ("movl %%esp, %0;",
83            Unsigned_32'Asm_Output ("=g", Context.Esp),
84            No_Input_Operands, "", True);
85
86       --  Save stack
87       pragma Validity_Checks (Off);
88       Context.Context_Stack := To_Save_Context_Stack_Ac (Context.Esp).all;
89       pragma Validity_Checks (On);
90
91       --  Push ebp to be restored after label "1:"
92       Asm ("pushl %%ebp;",
93            No_Output_Operands, No_Input_Operands, "", True);
94
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;",
99            No_Output_Operands,
100            No_Input_Operands, "", True);
101    end Save_Context;
102
103    ------------------
104    --  After_Jump  --
105    ------------------
106    --
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
112    begin
113       return Context.After_Jmp;
114    end After_Jump;
115
116    ---------------------
117    -- Restore_Context --
118    ---------------------
119    --
120    --  This procedure changes the return context of a preempted task.
121    --
122    --                    |        |               |       |
123    --  TCB_Ac.Stack_Ptr->|  Regs  |               |       |
124    --                    |        |               |       |
125    --                       ...                      ...
126    --                    |        |               |       |
127    --                    |        |               |Context|<-TCB_Ac.Stack_Ptr
128    --                    |        |<-Context.Esp->|       |
129    --                    |        |               |       |
130    --                    |        |               |       |
131    --                    |        |               |       |
132    --                      before                   after
133    --  The next time the task is scheduled will execute the final part of
134    --  Save_Context.
135    procedure Restore_Context (TCB_Ac  : System.Address;
136                               Context : access Jmp_Context) is
137
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
141          Tag : Unsigned_32;
142          Top_Of_Stack : Preempted_Task_Restore_Context_Stack_Ac;
143       end record;
144       type Beginning_Of_TCB_Ac is access Beginning_Of_TCB;
145
146       function UC  is
147         new Ada.Unchecked_Conversion (System.Address, Beginning_Of_TCB_Ac);
148       function UC  is
149         new Ada.Unchecked_Conversion (Unsigned_32,
150                                       Preempted_Task_Restore_Context_Stack_Ac);
151    begin
152
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);
157
158       --  Create new return context
159       UC (TCB_Ac).Top_Of_Stack.all :=
160         (Return_Address => Context.Return_Address,
161          Ebp            => Context.Ebp,
162          Context_Stack  => Context.Context_Stack);
163
164       --  The context has been used to perform a non-local jump
165       Context.After_Jmp := 1;
166    end Restore_Context;
167
168 end Non_Local_Jump;