gnat_riscv64_elf_13.2.1_938f208c/riscv64-elf/lib/gnat/light-tasking-polarfiresoc/gnarl/s-bbthre.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
------------------------------------------------------------------------------
--                                                                          --
--                  GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                --
--                                                                          --
--                       S Y S T E M . B B . T H R E A D S                  --
--                                                                          --
--                                  S p e c                                 --
--                                                                          --
--        Copyright (C) 1999-2002 Universidad Politecnica de Madrid         --
--             Copyright (C) 2003-2005 The European Space Agency            --
--                     Copyright (C) 2003-2023, AdaCore                     --
--                                                                          --
-- GNARL is free software; you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
-- GNARL was developed by the GNARL team at Florida State University.       --
-- Extensive contributions were provided by Ada Core Technologies, Inc.     --
--                                                                          --
-- The port of GNARL to bare board targets was initially developed by the   --
-- Real-Time Systems Group at the Technical University of Madrid.           --
--                                                                          --
------------------------------------------------------------------------------

--  Package that implements basic tasking functionalities

pragma Restrictions (No_Elaboration_Code);

with System.Storage_Elements;
with System.BB.CPU_Primitives;
with System.BB.Time;
with System.BB.Board_Support;
with System.Multiprocessors;

package System.BB.Threads is
   pragma Preelaborate;

   use type System.Multiprocessors.CPU;

   --------------------------
   -- Basic thread support --
   --------------------------

   Initialized : Boolean := False;
   --  Boolean that indicates whether the tasking executive has finished its
   --  initialization.

   type Thread_Descriptor;
   --  This type contains the information about a thread

   type Thread_Id is access all Thread_Descriptor;
   --  Type used as thread identifier

   Null_Thread_Id : constant Thread_Id := null;
   --  Identifier used to define an invalid value for a thread identifier

   type Thread_States is (Runnable, Suspended, Delayed);
   --  These are the three possible states for a thread under the Ravenscar
   --  profile restrictions: Runnable (not blocked, and it may also be
   --  executing), Suspended (waiting on an entry call), and Delayed (waiting
   --  on a delay until statement).

   type Thread_Descriptor is record
      Context : aliased System.BB.CPU_Primitives.Context_Buffer;
      --  Location where the hardware registers (stack pointer, program
      --  counter, ...) are stored. This field supports context switches among
      --  threads.

      --  It is important that the Context field is placed at the beginning of
      --  the record, because this assumption is using for implementing context
      --  switching. Take into account the alignment (8 bytes, 64 bits) to
      --  compute the required size.

      ATCB : System.Address;
      --  Address of the Ada Task Control Block corresponding to the Ada task
      --  that executes on this thread.

      Base_CPU : System.Multiprocessors.CPU_Range;
      --  CPU affinity of the thread

      Base_Priority : Integer;
      --  Base priority of the thread

      Active_Priority : Integer;
      pragma Volatile (Active_Priority);
      --  Active priority that differs from the base priority due to dynamic
      --  priority changes required by the Ceiling Priority Protocol.
      --  This field is marked as Volatile for a fast implementation
      --  of Get_Priority.

      Top_Of_Stack : System.Address;
      --  Address of the top of the stack that is used by the thread

      Bottom_Of_Stack : System.Address;
      --  Address of the bottom of the stack that is used by the thread

      Next : Thread_Id;
      --  Points to the ready thread that is in the next position for
      --  execution.

      Alarm_Time : System.BB.Time.Time;
      --  Time (absolute) when the alarm for this thread expires

      Next_Alarm : Thread_Id;
      --  Next thread in the alarm queue. The queue is ordered by expiration
      --  times. The first place is occupied by the thread which must be
      --  first awaken.

      State : Thread_States;
      --  Encodes some basic information about the state of a thread

      In_Interrupt : Boolean;
      pragma Volatile (In_Interrupt);
      --  True iff this task has been interrupted, and an interrupt handler
      --  is being executed.

      Wakeup_Signaled : Boolean;
      --  Variable which reflects whether another thread has performed a
      --  Wakeup operation on the thread. It may happen when a task is about
      --  to suspend itself, but it is preempted just before by the task that
      --  is going to awake it.

      Global_List : Thread_Id;
      --  Next thread in the global list. The queue is ordered by creation
      --  time. The first place is occupied by the environment thread, and
      --  it links all threads in the system.

      Execution_Time : System.BB.Time.Composite_Execution_Time;
      --  CPU time spent for this thread
   end record;

   function Get_Affinity
     (Thread : Thread_Id) return System.Multiprocessors.CPU_Range with
   --  Return CPU affinity of the given thread (maybe Not_A_Specific_CPU)

     Pre => Thread /= Null_Thread_Id,

     Inline => True;

   function Get_CPU
     (Thread : Thread_Id) return System.Multiprocessors.CPU with
   --  Return the CPU in charge of the given thread (always a valid CPU)

     Pre => Thread /= Null_Thread_Id,

     Inline => True;

   procedure Initialize
     (Environment_Thread : Thread_Id;
      Main_Priority      : System.Any_Priority) with
   --  Procedure to initialize the board and the data structures related to the
   --  low level tasking system. This procedure must be called before any other
   --  tasking operation. The operations to perform are:
   --    - Hardware initialization
   --       * Any board-specific initialization
   --       * Interrupts
   --       * Timer
   --    - Initialize stacks for main procedures to be executed on slave CPUs
   --    - Initialize the thread descriptor for the environment task
   --       * Set base CPU for the environment task to the one on which this
   --         initialization code executes
   --       * Set the base and active priority of the environment task
   --       * Store the boundaries of the stack for the environment task
   --       * Initialize the register context
   --    - Initialize the global queues
   --       * Set the environment task as first (and only at this moment) in
   --         the ready queue
   --       * Set the environment task as first (and only at this moment) in
   --         the global list of tasks
   --       * Set the environment task as the currently executing task
   --    - Initialize the floating point unit
   --    - Signal the flag corresponding to the initialization

     Pre =>

       --  This procedure must be called by the master CPU

       Board_Support.Multiprocessors.Current_CPU = Multiprocessors.CPU'First

       --  Initialization can only happen once

       and then not Initialized;

   procedure Initialize_Slave
     (Idle_Thread   : Thread_Id;
      Idle_Priority : Integer;
      Stack_Address : System.Address;
      Stack_Size    : System.Storage_Elements.Storage_Offset) with
   --  Procedure to initialize the idle thread on a slave CPU. The
   --  initialization for the main CPU must have been performed. The
   --  operations to perform are:
   --    - Initialize the thread descriptor
   --       * Set base CPU to the one on which this code executes
   --       * Set the base and active priority
   --       * Store the boundaries of the stack
   --       * Initialize the register context
   --    - Initialize the global queues
   --       * Set the task as the currently executing task in this processor.

     Pre =>

       --  It must happen after the initialization of the master CPU

       Initialized;

   procedure Thread_Create
     (Id            : Thread_Id;
      Code          : System.Address;
      Arg           : System.Address;
      Priority      : Integer;
      Base_CPU      : System.Multiprocessors.CPU_Range;
      Stack_Address : System.Address;
      Stack_Size    : System.Storage_Elements.Storage_Offset) with
   --  Create a new thread
   --
   --  The new thread executes the code at address Code and using Args as
   --  argument. Priority is the base priority of the new thread. The new
   --  thread is provided with a stack of size Stack_Size that has been
   --  preallocated at Stack_Address.
   --
   --  A procedure to destroy threads is not available because that is not
   --  allowed by the Ravenscar profile.

     Pre => Initialized;

   function Thread_Self return Thread_Id with
   --  Return the thread identifier of the calling thread

     Post => Thread_Self'Result /= Null_Thread_Id,

     Inline => True;

   ----------------
   -- Scheduling --
   ----------------

   procedure Set_Priority (Priority : Integer);
   pragma Inline (Set_Priority);
   --  Set the active priority of the executing thread to the given value

   function Get_Priority  (Id : Thread_Id) return Integer with
   --  Get the current active priority of any thread

     Pre => Id /= Null_Thread_Id,

     Inline => True;

   procedure Sleep;
   --  The calling thread is unconditionally suspended. In the case when there
   --  is a request to wakeup the caller just before the state changed to
   --  Suspended then the situation is signaled with the flag Wakeup_Signaled,
   --  and the call to Sleep consumes this token and the state remains
   --  Runnable.

   procedure Wakeup (Id : Thread_Id) with
   --  Thread Id becomes ready (the thread must be previously suspended). In
   --  the case when there is a request to wakeup the caller just before the
   --  state changed to Suspended then the situation is signaled with the
   --  flag Wakeup_Signaled (the state remains unchanged in this case).

     Pre =>
       Id /= Null_Thread_Id

       --  We can only wakeup a task that is already suspended or about to be
       --  suspended (and hence still runnable).

       and then Id.all.State in Suspended | Runnable

       --  Any wakeup previously signaled must have been consumed

       and then not Id.all.Wakeup_Signaled;

   ----------
   -- ATCB --
   ----------

   procedure Set_ATCB (Id : Thread_Id; ATCB : System.Address);
   pragma Inline (Set_ATCB);
   --  This procedure sets the ATCB passed as argument for the thread ID

   function Get_ATCB return System.Address;
   pragma Inline (Get_ATCB);
   --  Returns the ATCB of the currently executing thread

end System.BB.Threads;