]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - marte_non_local_jump/non_local_jump.adb
Updating marte_non_local_jump to new MaRTE OS file organisation
[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 with Marte.Hal;
27
28 package body Non_Local_Jump is
29    use Marte.Integer_Types;
30    use System;
31
32    pragma Optimize (Off);
33
34    -------------------
35    -- Save_Context --
36    -------------------
37    --
38    --  Context stores the information required to modify the stack of a
39    --  preempted task with 'Change_Return_Context_Of_Preempted_Task'.
40    --
41    --
42    procedure Save_Context (Context : access Jmp_Context) is
43       pragma Optimize (Off);
44
45       function To_Save_Context_Stack_Ac is
46         new Ada.Unchecked_Conversion (Unsigned_32, Save_Context_Stack_Ac);
47    begin
48       --  Store registers
49       Asm ("pushl %%eax;" &
50            "pushl %%ebp;" &
51            "pushl %%edi;" &
52            "pushl %%esi;" &
53            "pushl %%edx;" &
54            "pushl %%ecx;" &
55            "pushl %%ebx;"  &
56            "pushl $1f;",
57            No_Output_Operands, No_Input_Operands, "", True);
58
59       Asm ("popl %0 ;" &
60         "popl %1 ;" &
61         "popl %2 ;" &
62         "popl %3 ;" &
63         "popl %4 ;" &
64         "popl %5 ;" &
65         "popl %6 ;" &
66         "popl %7 ;",
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);
76
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);
81
82       --  Store esp
83       Asm ("movl %%esp, %0;",
84            Unsigned_32'Asm_Output ("=g", Context.Esp),
85            No_Input_Operands, "", True);
86
87       --  Save stack
88       pragma Validity_Checks (Off);
89       Context.Context_Stack := To_Save_Context_Stack_Ac (Context.Esp).all;
90       pragma Validity_Checks (On);
91
92       --  Push ebp to be restored after label "1:"
93       Asm ("pushl %%ebp;",
94            No_Output_Operands, No_Input_Operands, "", True);
95
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;",
100            No_Output_Operands,
101            No_Input_Operands, "", True);
102       Marte.Hal.Enable_Interrupts;
103    end Save_Context;
104
105    ------------------
106    --  After_Jump  --
107    ------------------
108    --
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
114    begin
115       return Context.After_Jmp;
116    end After_Jump;
117
118    ---------------------
119    -- Restore_Context --
120    ---------------------
121    --
122    --  This procedure changes the return context of a preempted task.
123    --
124    --                    |        |               |       |
125    --  TCB_Ac.Stack_Ptr->|  Regs  |               |       |
126    --                    |        |               |       |
127    --                       ...                      ...
128    --                    |        |               |       |
129    --                    |        |               |Context|<-TCB_Ac.Stack_Ptr
130    --                    |        |<-Context.Esp->|       |
131    --                    |        |               |       |
132    --                    |        |               |       |
133    --                    |        |               |       |
134    --                      before                   after
135    --  The next time the task is scheduled will execute the final part of
136    --  Save_Context.
137    procedure Restore_Context (TCB_Ac  : System.Address;
138                               Context : access Jmp_Context) is
139
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
143          Tag : Unsigned_32;
144          Top_Of_Stack : Preempted_Task_Restore_Context_Stack_Ac;
145       end record;
146       type Beginning_Of_TCB_Ac is access Beginning_Of_TCB;
147
148       function UC  is
149         new Ada.Unchecked_Conversion (System.Address, Beginning_Of_TCB_Ac);
150       function UC  is
151         new Ada.Unchecked_Conversion (Unsigned_32,
152                                       Preempted_Task_Restore_Context_Stack_Ac);
153    begin
154
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);
159
160       --  Create new return context
161       UC (TCB_Ac).Top_Of_Stack.all :=
162         (Return_Address => Context.Return_Address,
163          Ebp            => Context.Ebp,
164          Context_Stack  => Context.Context_Stack);
165
166       --  The context has been used to perform a non-local jump
167       Context.After_Jmp := 1;
168    end Restore_Context;
169
170 end Non_Local_Jump;