File : s-bbthre.ads


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                  GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                --
   4 --                                                                          --
   5 --                       S Y S T E M . B B . T H R E A D S                  --
   6 --                                                                          --
   7 --                                  S p e c                                 --
   8 --                                                                          --
   9 --        Copyright (C) 1999-2002 Universidad Politecnica de Madrid         --
  10 --             Copyright (C) 2003-2005 The European Space Agency            --
  11 --                     Copyright (C) 2003-2016, AdaCore                     --
  12 --                                                                          --
  13 -- GNARL is free software; you can  redistribute it  and/or modify it under --
  14 -- terms of the  GNU General Public License as published  by the Free Soft- --
  15 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  16 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
  17 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
  19 --                                                                          --
  20 --                                                                          --
  21 --                                                                          --
  22 --                                                                          --
  23 --                                                                          --
  24 -- You should have received a copy of the GNU General Public License and    --
  25 -- a copy of the GCC Runtime Library Exception along with this program;     --
  26 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
  27 -- <http://www.gnu.org/licenses/>.                                          --
  28 --                                                                          --
  29 -- GNARL was developed by the GNARL team at Florida State University.       --
  30 -- Extensive contributions were provided by Ada Core Technologies, Inc.     --
  31 --                                                                          --
  32 -- The port of GNARL to bare board targets was initially developed by the   --
  33 -- Real-Time Systems Group at the Technical University of Madrid.           --
  34 --                                                                          --
  35 ------------------------------------------------------------------------------
  36 
  37 --  Package that implements basic tasking functionalities
  38 
  39 pragma Restrictions (No_Elaboration_Code);
  40 
  41 with System;
  42 with System.Storage_Elements;
  43 with System.BB.CPU_Primitives;
  44 with System.BB.Time;
  45 with System.BB.Interrupts;
  46 with System.Multiprocessors;
  47 with System.BB.CPU_Primitives.Multiprocessors;
  48 
  49 package System.BB.Threads is
  50    pragma Preelaborate;
  51 
  52    use type System.Multiprocessors.CPU;
  53 
  54    --------------------------
  55    -- Basic thread support --
  56    --------------------------
  57 
  58    Initialized : Boolean := False;
  59    --  Boolean that indicates whether the tasking executive has finished its
  60    --  initialization.
  61 
  62    type Thread_Descriptor;
  63    --  This type contains the information about a thread
  64 
  65    type Thread_Id is access all Thread_Descriptor;
  66    --  Type used as thread identifier
  67 
  68    Null_Thread_Id : constant Thread_Id := null;
  69    --  Identifier used to define an invalid value for a thread identifier
  70 
  71    type Thread_States is (Runnable, Suspended, Delayed);
  72    --  These are the three possible states for a thread under the Ravenscar
  73    --  profile restrictions: Runnable (not blocked, and it may also be
  74    --  executing), Suspended (waiting on an entry call), and Delayed (waiting
  75    --  on a delay until statement).
  76 
  77    type Thread_Descriptor is record
  78       Context : aliased System.BB.CPU_Primitives.Context_Buffer;
  79       --  Location where the hardware registers (stack pointer, program
  80       --  counter, ...) are stored. This field supports context switches among
  81       --  threads.
  82 
  83       --  It is important that the Context field is placed at the beginning of
  84       --  the record, because this assumption is using for implementing context
  85       --  switching. Take into account the alignment (8 bytes, 64 bits) to
  86       --  compute the required size.
  87 
  88       ATCB : System.Address;
  89       --  Address of the Ada Task Control Block corresponding to the Ada task
  90       --  that executes on this thread.
  91 
  92       Base_CPU : System.Multiprocessors.CPU_Range;
  93       --  CPU affinity of the thread
  94 
  95       Base_Priority : Integer;
  96       --  Base priority of the thread
  97 
  98       Active_Priority : Integer;
  99       pragma Volatile (Active_Priority);
 100       --  Active priority that differs from the base priority due to dynamic
 101       --  priority changes required by the Ceiling Priority Protocol.
 102       --  This field is marked as Volatile for a fast implementation
 103       --  of Get_Priority.
 104 
 105       Top_Of_Stack : System.Address;
 106       --  Address of the top of the stack that is used by the thread
 107 
 108       Bottom_Of_Stack : System.Address;
 109       --  Address of the bottom of the stack that is used by the thread
 110 
 111       Next : Thread_Id;
 112       --  Points to the ready thread that is in the next position for
 113       --  execution.
 114 
 115       Alarm_Time : System.BB.Time.Time;
 116       --  Time (absolute) when the alarm for this thread expires
 117 
 118       Next_Alarm : Thread_Id;
 119       --  Next thread in the alarm queue. The queue is ordered by expiration
 120       --  times. The first place is occupied by the thread which must be
 121       --  first awaken.
 122 
 123       State : Thread_States;
 124       --  Encodes some basic information about the state of a thread
 125 
 126       In_Interrupt : Boolean;
 127       pragma Volatile (In_Interrupt);
 128       --  True iff this task has been interrupted, and an interrupt handler
 129       --  is being executed.
 130 
 131       Wakeup_Signaled : Boolean;
 132       --  Variable which reflects whether another thread has performed a
 133       --  Wakeup operation on the thread. It may happen when a task is about
 134       --  to suspend itself, but it is preempted just before by the task that
 135       --  is going to awake it.
 136 
 137       Global_List : Thread_Id;
 138       --  Next thread in the global list. The queue is ordered by creation
 139       --  time. The first place is occupied by the environment thread, and
 140       --  it links all threads in the system.
 141 
 142       Execution_Time : System.BB.Time.Composite_Execution_Time;
 143       --  CPU time spent for this thread
 144    end record;
 145 
 146    function Get_Affinity
 147      (Thread : Thread_Id) return System.Multiprocessors.CPU_Range with
 148    --  Return CPU affinity of the given thread (maybe Not_A_Specific_CPU)
 149 
 150      Pre => Thread /= Null_Thread_Id,
 151 
 152      Inline => True;
 153 
 154    function Get_CPU
 155      (Thread : Thread_Id) return System.Multiprocessors.CPU with
 156    --  Return the CPU in charge of the given thread (always a valid CPU)
 157 
 158      Pre => Thread /= Null_Thread_Id,
 159 
 160      Inline => True;
 161 
 162    procedure Initialize
 163      (Environment_Thread : Thread_Id;
 164       Main_Priority      : System.Any_Priority) with
 165    --  Procedure to initialize the board and the data structures related to the
 166    --  low level tasking system. This procedure must be called before any other
 167    --  tasking operation. The operations to perform are:
 168    --    - Hardware initialization
 169    --       * Any board-specific initialization
 170    --       * Interrupts
 171    --       * Timer
 172    --    - Initialize stacks for main procedures to be executed on slave CPUs
 173    --    - Initialize the thread descriptor for the environment task
 174    --       * Set base CPU for the environment task to the one on which this
 175    --         initialization code executes
 176    --       * Set the base and active priority of the environment task
 177    --       * Store the boundaries of the stack for the environment task
 178    --       * Initialize the register context
 179    --    - Initialize the global queues
 180    --       * Set the environment task as first (and only at this moment) in
 181    --         the ready queue
 182    --       * Set the environment task as first (and only at this moment) in
 183    --         the global list of tasks
 184    --       * Set the environment task as the currently executing task
 185    --    - Initialize the floating point unit
 186    --    - Signal the flag corresponding to the initialization
 187 
 188      Pre =>
 189 
 190        --  This procedure must be called by the master CPU
 191 
 192        CPU_Primitives.Multiprocessors.Current_CPU = Multiprocessors.CPU'First
 193 
 194        --  Initialization can only happen once
 195 
 196        and then not Initialized;
 197 
 198    procedure Initialize_Slave
 199      (Idle_Thread   : Thread_Id;
 200       Idle_Priority : Integer;
 201       Stack_Address : System.Address;
 202       Stack_Size    : System.Storage_Elements.Storage_Offset) with
 203    --  Procedure to initialize the idle thread on a slave CPU.
 204    --  This thread is used to handle interrupt if the CPU doesn't have any
 205    --  other task. The initialization for the main CPU must have been
 206    --  performed. The operations to perform are:
 207    --    - Initialize the thread descriptor
 208    --       * Set base CPU to the one on which this code executes
 209    --       * Set the base and active priority
 210    --       * Store the boundaries of the stack
 211    --       * Initialize the register context
 212    --    - Initialize the global queues
 213    --       * Set the task as the currently executing task in this processor.
 214 
 215      Pre =>
 216 
 217        --  It must happen after the initialization of the master CPU
 218 
 219        Initialized;
 220 
 221    procedure Thread_Create
 222      (Id            : Thread_Id;
 223       Code          : System.Address;
 224       Arg           : System.Address;
 225       Priority      : Integer;
 226       Base_CPU      : System.Multiprocessors.CPU_Range;
 227       Stack_Address : System.Address;
 228       Stack_Size    : System.Storage_Elements.Storage_Offset) with
 229    --  Create a new thread
 230    --
 231    --  The new thread executes the code at address Code and using Args as
 232    --  argument. Priority is the base priority of the new thread. The new
 233    --  thread is provided with a stack of size Stack_Size that has been
 234    --  preallocated at Stack_Address.
 235    --
 236    --  A procedure to destroy threads is not available because that is not
 237    --  allowed by the Ravenscar profile.
 238 
 239      Pre => Initialized;
 240 
 241    function Thread_Self return Thread_Id with
 242    --  Return the thread identifier of the calling thread
 243 
 244      Post => Thread_Self'Result /= Null_Thread_Id,
 245 
 246      Inline => True;
 247 
 248    ----------------
 249    -- Scheduling --
 250    ----------------
 251 
 252    procedure Set_Priority (Priority : Integer);
 253    pragma Inline (Set_Priority);
 254    --  Set the active priority of the executing thread to the given value
 255 
 256    function Get_Priority  (Id : Thread_Id) return Integer with
 257    --  Get the current active priority of any thread
 258 
 259      Pre => Id /= Null_Thread_Id,
 260 
 261      Inline => True;
 262 
 263    procedure Sleep;
 264    --  The calling thread is unconditionally suspended. In the case when there
 265    --  is a request to wakeup the caller just before the state changed to
 266    --  Suspended then the situation is signaled with the flag Wakeup_Signaled,
 267    --  and the call to Sleep consumes this token and the state remains
 268    --  Runnable.
 269 
 270    procedure Wakeup (Id : Thread_Id) with
 271    --  Thread Id becomes ready (the thread must be previously suspended). In
 272    --  the case when there is a request to wakeup the caller just before the
 273    --  state changed to Suspended then the situation is signaled with the
 274    --  flag Wakeup_Signaled (the state remains unchanged in this case).
 275 
 276      Pre =>
 277        Id /= Null_Thread_Id
 278 
 279        --  We can only wakeup a task that is already suspended or about to be
 280        --  suspended (and hence still runnable).
 281 
 282        and then Id.all.State in Suspended | Runnable
 283 
 284        --  Any wakeup previously signaled must have been consumed
 285 
 286        and then not Id.all.Wakeup_Signaled;
 287 
 288    ----------
 289    -- ATCB --
 290    ----------
 291 
 292    procedure Set_ATCB (Id : Thread_Id; ATCB : System.Address);
 293    pragma Inline (Set_ATCB);
 294    --  This procedure sets the ATCB passed as argument for the thread ID
 295 
 296    function Get_ATCB return System.Address;
 297    pragma Inline (Get_ATCB);
 298    --  Returns the ATCB of the currently executing thread
 299 
 300 end System.BB.Threads;