File : s-bbtime.ads


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                  GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                --
   4 --                                                                          --
   5 --                         S Y S T E M . B B . T I M E                      --
   6 --                                                                          --
   7 --                                  S p e c                                 --
   8 --                                                                          --
   9 --        Copyright (C) 1999-2002 Universidad Politecnica de Madrid         --
  10 --             Copyright (C) 2003-2004 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 in charge of implementing clock and timer functionalities
  38 
  39 pragma Restrictions (No_Elaboration_Code);
  40 
  41 with System.Multiprocessors;
  42 
  43 package System.BB.Time is
  44    pragma Preelaborate;
  45 
  46    type Time is mod 2 ** 64;
  47    for Time'Size use 64;
  48 
  49    ------------------
  50    -- Time keeping --
  51    ------------------
  52 
  53    --  Time is represented at this level as a 64-bit unsigned number. We assume
  54    --  that the Board_Support.Read_Clock function provides access to a hardware
  55    --  clock with a resolution of 20 microseconds or better, counting from
  56    --  0 to Board_Support.Max_Timer_Interval over a period of at least 0.735
  57    --  seconds, and returning a value of the 32-bit Timer_Interval type. The
  58    --  clock resolution should be an integral number of nanoseconds between 1
  59    --  and 20_000.
  60 
  61    --  In addition, Board_Support provides an alarm facility, generating an
  62    --  alarm interrupt at up to Max_Timer_Interval clock ticks in the future.
  63    --  The clock frequency is the same as for Read_Clock, but it may or may not
  64    --  use the same timer. See the next section for more information.
  65 
  66    --  The Time package uses these facilities to keep a 64-bit clock that will
  67    --  allow a program to keep track of up to 50 years in the future without
  68    --  having the most significant bit set. This means it is always safe to
  69    --  subtract two Clock readings to determine a Time_Span without overflow.
  70 
  71    --  We need to support a clock running for 50 years, so this requires
  72    --  a hardware clock period of at least 1_577_880_000 / 2**31 or 0.735
  73    --  seconds. As comparison, a LEON2 at 80 MHz with 24-bit clock and the
  74    --  minimum prescale factor of 4, has a period of 2**24 / (80E6 / 4) = 0.839
  75    --  seconds, while a 200 MHz LEON3 has a period of 2**32 / (200E6 / 5) =
  76    --  107 seconds. For faster clocks or smaller clock width, higher prescaler
  77    --  values may be needed to achieve 50 year run time. The prescale factor
  78    --  should be chosen such that the period between clock ticks is an integral
  79    --  number of nanoseconds between 1 and 20_000.
  80 
  81    type Time_Span is range -2 ** 63 .. 2 ** 63 - 1;
  82    for Time_Span'Size use 64;
  83    --  Time_Span represents the length of time intervals, and it is defined as
  84    --  a 64-bit signed integer.
  85 
  86    ------------
  87    -- Alarms --
  88    ------------
  89 
  90    --  Alarms are used for two purposes:
  91 
  92    --    * Waking up tasks that sleep as result of Delay_Until
  93 
  94    --    * Clock updates, to prevent undetected wrap-around of the
  95    --      hardware clock
  96 
  97    --  Alarms use the same time unit as the clock used for time keeping,
  98    --  and need to be able to provide an alarm up to slightly less than
  99    --  Max_Timer_Interval ticks in the future; there always will be a pending
 100    --  alarm within this time frame because of required clock updates. A
 101    --  requirement is that an alarm always can be handled within 1/8th of the
 102    --  time it takes the hardware clock to wrap around. This gives an upper
 103    --  bound to how early we have to set the alarm to ensure timely clock
 104    --  updates. This will result in an interrupt rate 14% higher than
 105    --  absolutely necessary. However, as long as sleep-related alarms are
 106    --  sufficiently frequent, no extra clock-related interrupts are necessary.
 107 
 108    --------------------
 109    -- Execution time --
 110    --------------------
 111 
 112    --  System.BB.Execution_Time will set these hooks to enable execution time
 113    --  computation only when needed.
 114 
 115    Scheduling_Event_Hook : access procedure := null;
 116    --  This hooks must be called when the charged account change: in case of
 117    --  rescheduling and before and after the handling of interrupt.
 118 
 119    --------------------
 120    -- Initialization --
 121    --------------------
 122 
 123    procedure Initialize_Timers;
 124    --  Initialize this package (clock and alarm handlers). Must be called
 125    --  before any other functions.
 126 
 127    ----------------
 128    -- Operations --
 129    ----------------
 130 
 131    function Epoch return Time;
 132    --  Get the reference startup time
 133 
 134    function Clock return Time;
 135    --  Get the number of ticks elapsed since startup
 136 
 137    procedure Delay_Until (T : Time);
 138    --  Suspend the calling thread until the absolute time specified by T
 139 
 140    function Get_Next_Timeout (CPU_Id : System.Multiprocessors.CPU) return Time;
 141    --  Get the date of the next alarm or timing event
 142 
 143    procedure Update_Alarm (Alarm : Time);
 144    --  Re-configure the timer if "Alarm" is earlier than the Pending_Alarm.
 145    --  Update_Alarm is the only routine allowed to set an alarm.
 146 
 147    --  Execution time
 148 
 149    --  Ada allows reading the execution time of any task. To support that, we
 150    --  need to have exclusive access to the time (which is costly as it is not
 151    --  possible to atomically read that value without using a spin lock and
 152    --  masking interrupts). To avoid that cost, let's split that type in two
 153    --  parts (that can be read or written atomically by the processor). It
 154    --  is not possible to read atomically the whole value, but it is possible
 155    --  to read a coherent value: if the time has been changed from A to B
 156    --  while being read, the value read is between A and B. Because of the
 157    --  architecture of the runtime, the execution time is always written
 158    --  atomically (written by the processor executing the task, within the
 159    --  kernel).
 160 
 161    --  The type Composite_Execution_Time is declared here so that s-bbthre
 162    --  doesn't depend on s-bbtiev. But this type is used by s-bbtiev.
 163 
 164    type Word is mod 2 ** 32;
 165 
 166    type Composite_Execution_Time is record
 167       High : Word;
 168       pragma Atomic (High);
 169       --  High part of execution time
 170 
 171       Low : Word;
 172       pragma Atomic (Low);
 173       --  Low part of execution time
 174    end record;
 175 
 176    Initial_Composite_Execution_Time : constant Composite_Execution_Time :=
 177                                                                      (0, 0);
 178    --  The initial value for Composite_Execution_Time
 179 
 180 private
 181    pragma Inline (Clock);
 182    pragma Inline (Epoch);
 183 
 184 end System.BB.Time;