* adaint.c: Minor cleanups.
[platform/upstream/gcc.git] / gcc / ada / 5oosinte.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                 GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS              --
4 --                                                                          --
5 --                   S Y S T E M . O S _ I N T E R F A C E                  --
6 --                                                                          --
7 --                                  B o d y                                 --
8 --                                                                          --
9 --                             $Revision$
10 --                                                                          --
11 --            Copyright (C) 1991-2001 Florida State University              --
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 2,  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.  See the GNU General Public License --
19 -- for  more details.  You should have  received  a copy of the GNU General --
20 -- Public License  distributed with GNARL; see file COPYING.  If not, write --
21 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
22 -- MA 02111-1307, USA.                                                      --
23 --                                                                          --
24 -- As a special exception,  if other files  instantiate  generics from this --
25 -- unit, or you link  this unit with other files  to produce an executable, --
26 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
27 -- covered  by the  GNU  General  Public  License.  This exception does not --
28 -- however invalidate  any other reasons why  the executable file  might be --
29 -- covered by the  GNU Public License.                                      --
30 --                                                                          --
31 -- GNARL was developed by the GNARL team at Florida State University. It is --
32 -- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
33 -- State University (http://www.gnat.com).                                  --
34 --                                                                          --
35 ------------------------------------------------------------------------------
36
37 --  This is the OS/2 version of this package
38
39 pragma Polling (Off);
40 --  Turn off polling, we do not want ATC polling to take place during
41 --  tasking operations. It causes infinite loops and other problems.
42
43 with Interfaces.C.Strings;
44 with Interfaces.OS2Lib.Errors;
45 with Interfaces.OS2Lib.Synchronization;
46
47 package body System.OS_Interface is
48
49    use Interfaces;
50    use Interfaces.OS2Lib;
51    use Interfaces.OS2Lib.Synchronization;
52    use Interfaces.OS2Lib.Errors;
53
54    ------------------
55    -- Timer (spec) --
56    ------------------
57
58    --  Although the OS uses a 32-bit integer representing milliseconds
59    --  as timer value that doesn't work for us since 32 bits are not
60    --  enough for absolute timing. Also it is useful to use better
61    --  intermediate precision when adding/substracting timing intervals.
62    --  So we use the standard Ada Duration type which is implemented using
63    --  microseconds.
64
65    --  Shouldn't the timer be moved to a separate package ???
66
67    type Timer is record
68       Handle : aliased HTIMER := NULLHANDLE;
69       Event  : aliased HEV    := NULLHANDLE;
70    end record;
71
72    procedure Initialize (T :    out Timer);
73    procedure Finalize   (T : in out Timer);
74    procedure Wait       (T : in out Timer);
75    procedure Reset      (T : in out Timer);
76
77    procedure Set_Timer_For (T : in out Timer; Period : in Duration);
78    procedure Set_Timer_At  (T : in out Timer; Time   : in Duration);
79    --  Add a hook to locate the Epoch, for use with Calendar????
80
81    -----------
82    -- Yield --
83    -----------
84
85    --  Give up the remainder of the time-slice and yield the processor
86    --  to other threads of equal priority. Yield will return immediately
87    --  without giving up the current time-slice when the only threads
88    --  that are ready have a lower priority.
89
90    --  ???  Just giving up the current time-slice seems not to be enough
91    --  to get the thread to the end of the ready queue if OS/2 does use
92    --  a queue at all. As a partial work-around, we give up two time-slices.
93
94    --  This is the best we can do now, and at least is sufficient for passing
95    --  the ACVC 2.0.1 Annex D tests.
96
97    procedure Yield is
98    begin
99       Delay_For (0);
100       Delay_For (0);
101    end Yield;
102
103    ---------------
104    -- Delay_For --
105    ---------------
106
107    procedure Delay_For (Period : in Duration_In_Millisec) is
108       Result : APIRET;
109
110    begin
111       pragma Assert (Period >= 0, "GNULLI---Delay_For: negative argument");
112
113       --  ??? DosSleep is not the appropriate function for a delay in real
114       --  time. It only gives up some number of scheduled time-slices.
115       --  Use a timer instead or block for some semaphore with a time-out.
116       Result := DosSleep (ULONG (Period));
117
118       if Result = ERROR_TS_WAKEUP then
119
120          --  Do appropriate processing for interrupted sleep
121          --  Can we raise an exception here?
122
123          null;
124       end if;
125
126       pragma Assert (Result = NO_ERROR, "GNULLI---Error in Delay_For");
127    end Delay_For;
128
129    -----------
130    -- Clock --
131    -----------
132
133    function Clock return Duration is
134
135       --  Implement conversion from tick count to Duration
136       --  using fixed point arithmetic. The frequency of
137       --  the Intel 8254 timer chip is 18.2 * 2**16 Hz.
138
139       Tick_Duration : constant := 1.0 / (18.2 * 2**16);
140       Tick_Count    : aliased QWORD;
141
142    begin
143
144       --  Read nr of clock ticks since boot time
145       Must_Not_Fail (DosTmrQueryTime (Tick_Count'Access));
146
147       return Tick_Count * Tick_Duration;
148    end Clock;
149
150    ----------------------
151    -- Initialize Timer --
152    ----------------------
153
154    procedure Initialize (T : out Timer) is
155    begin
156       pragma Assert
157         (T.Handle = NULLHANDLE, "GNULLI---Timer already initialized");
158
159       Must_Not_Fail (DosCreateEventSem
160         (pszName => Interfaces.C.Strings.Null_Ptr,
161          f_phev  => T.Event'Unchecked_Access,
162          flAttr  => DC_SEM_SHARED,
163          fState  => False32));
164    end Initialize;
165
166    -------------------
167    -- Set_Timer_For --
168    -------------------
169
170    procedure Set_Timer_For
171      (T         : in out Timer;
172       Period    : in Duration)
173    is
174       Rel_Time  : Duration_In_Millisec :=
175                     Duration_In_Millisec (Period * 1_000.0);
176
177    begin
178       pragma Assert
179         (T.Event /= NULLHANDLE, "GNULLI---Timer not initialized");
180       pragma Assert
181         (T.Handle = NULLHANDLE, "GNULLI---Timer already in use");
182
183       Must_Not_Fail (DosAsyncTimer
184         (msec      => ULONG (Rel_Time),
185          F_hsem    => HSEM (T.Event),
186          F_phtimer => T.Handle'Unchecked_Access));
187    end Set_Timer_For;
188
189    ------------------
190    -- Set_Timer_At --
191    ------------------
192
193    --  Note that the timer is started in a critical section to prevent the
194    --  race condition when absolute time is converted to time relative to
195    --  current time. T.Event will be posted when the Time has passed
196
197    procedure Set_Timer_At
198      (T         : in out Timer;
199       Time      : in Duration)
200    is
201       Relative_Time : Duration;
202
203    begin
204       Must_Not_Fail (DosEnterCritSec);
205
206       begin
207          Relative_Time := Time - Clock;
208          if Relative_Time >  0.0 then
209             Set_Timer_For (T, Period => Time - Clock);
210          else
211             Sem_Must_Not_Fail (DosPostEventSem (T.Event));
212          end if;
213       end;
214
215       Must_Not_Fail (DosExitCritSec);
216    end Set_Timer_At;
217
218    ----------
219    -- Wait --
220    ----------
221
222    procedure Wait (T : in out Timer) is
223    begin
224       Sem_Must_Not_Fail (DosWaitEventSem (T.Event, SEM_INDEFINITE_WAIT));
225       T.Handle := NULLHANDLE;
226    end Wait;
227
228    -----------
229    -- Reset --
230    -----------
231
232    procedure Reset (T : in out Timer) is
233       Dummy_Count : aliased ULONG;
234
235    begin
236       if T.Handle /= NULLHANDLE then
237          Must_Not_Fail (DosStopTimer (T.Handle));
238          T.Handle := NULLHANDLE;
239       end if;
240
241       Sem_Must_Not_Fail
242         (DosResetEventSem (T.Event, Dummy_Count'Unchecked_Access));
243    end Reset;
244
245    --------------
246    -- Finalize --
247    --------------
248
249    procedure Finalize (T : in out Timer) is
250    begin
251       Reset (T);
252       Must_Not_Fail (DosCloseEventSem (T.Event));
253       T.Event := NULLHANDLE;
254    end Finalize;
255
256 end System.OS_Interface;