File : s-bcprmu-leon3.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
4 -- --
5 -- SYSTEM.BB.CPU_PRIMITIVES.MULTIPROCESSORS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2010-2016, AdaCore --
10 -- --
11 -- GNARL is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- --
19 -- --
20 -- --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 ------------------------------------------------------------------------------
28
29 pragma Restrictions (No_Elaboration_Code);
30
31 with System.Machine_Code;
32 with System.BB.Time;
33 with System.BB.Timing_Events;
34 with System.BB.Board_Support;
35 with System.BB.Board_Support.LEON_3;
36 with System.BB.Interrupts;
37 with System.BB.Threads;
38 with System.BB.Threads.Queues;
39 with System.BB.Protection;
40 with Interfaces;
41
42 package body System.BB.CPU_Primitives.Multiprocessors is
43
44 use System.Machine_Code;
45 use Board_Support;
46 use Board_Support.LEON_3;
47 use Interfaces;
48 use System.Multiprocessors;
49
50 procedure Poke_Handler (Interrupt : Interrupts.Interrupt_ID);
51 -- Handler for the Poke interrupt
52
53 function ASR_17 return Unsigned_32;
54 -- Return current value of the ASR 17 register
55
56 ------------
57 -- ASR_17 --
58 ------------
59
60 function ASR_17 return Unsigned_32 is
61 R : Unsigned_32;
62 begin
63 Asm ("mov %%asr17, %0" & ASCII.LF & ASCII.HT,
64 Outputs => Unsigned_32'Asm_Output ("=r", R),
65 Volatile => True);
66 return R;
67 end ASR_17;
68
69 -----------------
70 -- Current_CPU --
71 -----------------
72
73 function Current_CPU return CPU is
74
75 -- Get CPU Id from bits 31-28 of the Asr17 register
76
77 (if CPU'Last = 1 then 1 else CPU (Shift_Right (ASR_17, 28) + 1));
78
79 --------------
80 -- Poke_CPU --
81 --------------
82
83 procedure Poke_CPU (CPU_Id : CPU) is
84 begin
85 -- There is no need to protect access to the register since the only
86 -- operation applied to it is this assignment and it's always with the
87 -- same value (2**Poke_Interrupt_ID).
88
89 -- No race condition possible here.
90
91 Interrupt_Force (CPU_Id) :=
92 Interrupt_Force (CPU_Id) or 2**Poke_Interrupt_ID;
93 end Poke_CPU;
94
95 ---------------
96 -- Start_CPU --
97 ---------------
98
99 procedure Start_CPU (CPU_Id : CPU) is
100 Reg : Multiprocessor_Status_Register;
101 begin
102 -- Set bit n in Status Register to start CPU n
103
104 Reg := Multiprocessor_Status;
105 Reg.Status := 2**(CPU'Pos (CPU_Id) - 1);
106 Multiprocessor_Status := Reg;
107 end Start_CPU;
108
109 --------------------
110 -- Start_All_CPUs --
111 --------------------
112
113 procedure Start_All_CPUs is
114 begin
115 -- Nothing to do when there's only one CPU
116
117 if CPU'Range_Length > 1 then
118 Interrupts.Attach_Handler
119 (Poke_Handler'Access, Poke_Interrupt_ID, Interrupt_Priority'Last);
120
121 for CPU_Id in CPU'First + 1 .. CPU'Last loop
122 Start_CPU (CPU_Id);
123 end loop;
124 end if;
125 end Start_All_CPUs;
126
127 ------------------
128 -- Poke_Handler --
129 ------------------
130
131 procedure Poke_Handler (Interrupt : Interrupts.Interrupt_ID) is
132 use type Threads.Thread_States;
133
134 Now : Time.Time;
135
136 begin
137 -- Make sure we are handling the right interrupt
138
139 pragma Assert (Interrupt = Board_Support.Poke_Interrupt_ID);
140
141 Board_Support.Clear_Poke_Interrupt;
142
143 -- The access to the queues must be protected
144
145 Protection.Enter_Kernel;
146
147 Now := Time.Clock;
148
149 -- Execute expired events of the current CPU
150
151 Timing_Events.Execute_Expired_Timing_Events (Now);
152
153 -- Wake up alarms
154
155 Threads.Queues.Wakeup_Expired_Alarms (Now);
156
157 Protection.Leave_Kernel;
158 end Poke_Handler;
159
160 end System.BB.CPU_Primitives.Multiprocessors;