summaryrefslogtreecommitdiff
path: root/gcc/ada/5htaprop.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/5htaprop.adb')
-rw-r--r--gcc/ada/5htaprop.adb292
1 files changed, 132 insertions, 160 deletions
diff --git a/gcc/ada/5htaprop.adb b/gcc/ada/5htaprop.adb
index 08d2a7ee34c..7efc38806ae 100644
--- a/gcc/ada/5htaprop.adb
+++ b/gcc/ada/5htaprop.adb
@@ -6,9 +6,9 @@
-- --
-- B o d y --
-- --
--- $Revision: 1.1 $
+-- $Revision$
-- --
--- Copyright (C) 1991-2001, Florida State University --
+-- Copyright (C) 1992-2001, Free Software Foundation, Inc. --
-- --
-- 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- --
@@ -29,12 +29,11 @@
-- covered by the GNU Public License. --
-- --
-- GNARL was developed by the GNARL team at Florida State University. It is --
--- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
--- State University (http://www.gnat.com). --
+-- now maintained by Ada Core Technologies, Inc. (http://www.gnat.com). --
-- --
------------------------------------------------------------------------------
--- This is a HP-UX version of this package
+-- This is a HP-UX DCE threads version of this package
-- This package contains all the GNULL primitives that interface directly
-- with the underlying OS.
@@ -106,8 +105,10 @@ package body System.Task_Primitives.Operations is
ATCB_Key : aliased pthread_key_t;
-- Key used to find the Ada Task_ID associated with a thread
- All_Tasks_L : aliased System.Task_Primitives.RTS_Lock;
- -- See comments on locking rules in System.Tasking (spec).
+ Single_RTS_Lock : aliased RTS_Lock;
+ -- This is a lock to allow only one thread of control in the RTS at
+ -- a time; it is used to execute in mutual exclusion from all other tasks.
+ -- Used mainly in Single_Lock mode, but also to protect All_Tasks_List
Environment_Task_ID : Task_ID;
-- A variable to hold Task_ID for the environment task.
@@ -143,53 +144,12 @@ package body System.Task_Primitives.Operations is
-- Abort_Handler --
-------------------
- -- Target-dependent binding of inter-thread Abort signal to
- -- the raising of the Abort_Signal exception.
-
- -- The technical issues and alternatives here are essentially
- -- the same as for raising exceptions in response to other
- -- signals (e.g. Storage_Error). See code and comments in
- -- the package body System.Interrupt_Management.
-
- -- Some implementations may not allow an exception to be propagated
- -- out of a handler, and others might leave the signal or
- -- interrupt that invoked this handler masked after the exceptional
- -- return to the application code.
-
- -- GNAT exceptions are originally implemented using setjmp()/longjmp().
- -- On most UNIX systems, this will allow transfer out of a signal handler,
- -- which is usually the only mechanism available for implementing
- -- asynchronous handlers of this kind. However, some
- -- systems do not restore the signal mask on longjmp(), leaving the
- -- abort signal masked.
-
- -- Alternative solutions include:
-
- -- 1. Change the PC saved in the system-dependent Context
- -- parameter to point to code that raises the exception.
- -- Normal return from this handler will then raise
- -- the exception after the mask and other system state has
- -- been restored (see example below).
- -- 2. Use siglongjmp()/sigsetjmp() to implement exceptions.
- -- 3. Unmask the signal in the Abortion_Signal exception handler
- -- (in the RTS).
-
- -- The following procedure would be needed if we can't lonjmp out of
- -- a signal handler. (See below.)
- -- procedure Raise_Abort_Signal is
- -- begin
- -- raise Standard'Abort_Signal;
- -- end if;
-
procedure Abort_Handler (Sig : Signal) is
Self_Id : constant Task_ID := Self;
Result : Interfaces.C.int;
Old_Set : aliased sigset_t;
begin
- -- Assuming it is safe to longjmp out of a signal handler, the
- -- following code can be used:
-
if Self_Id.Deferral_Level = 0
and then Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level and then
not Self_Id.Aborting
@@ -204,15 +164,6 @@ package body System.Task_Primitives.Operations is
raise Standard'Abort_Signal;
end if;
-
- -- Otherwise, something like this is required:
- -- if not Abort_Is_Deferred.all then
- -- -- Overwrite the return PC address with the address of the
- -- -- special raise routine, and "return" to that routine's
- -- -- starting address.
- -- Context.PC := Raise_Abort_Signal'Address;
- -- return;
- -- end if;
end Abort_Handler;
-----------------
@@ -243,7 +194,6 @@ package body System.Task_Primitives.Operations is
function Self return Task_ID is
Result : System.Address;
-
begin
Result := pthread_getspecific (ATCB_Key);
pragma Assert (Result /= System.Null_Address);
@@ -256,7 +206,7 @@ package body System.Task_Primitives.Operations is
-- Note: mutexes and cond_variables needed per-task basis are
-- initialized in Initialize_TCB and the Storage_Error is
- -- handled. Other mutexes (such as All_Tasks_Lock, Memory_Lock...)
+ -- handled. Other mutexes (such as RTS_Lock, Memory_Lock...)
-- used in RTS is initialized before any status change of RTS.
-- Therefore rasing Storage_Error in the following routines
-- should be able to be handled safely.
@@ -266,7 +216,8 @@ package body System.Task_Primitives.Operations is
L : access Lock)
is
Attributes : aliased pthread_mutexattr_t;
- Result : Interfaces.C.int;
+ Result : Interfaces.C.int;
+
begin
Result := pthread_mutexattr_init (Attributes'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
@@ -290,7 +241,7 @@ package body System.Task_Primitives.Operations is
procedure Initialize_Lock (L : access RTS_Lock; Level : Lock_Level) is
Attributes : aliased pthread_mutexattr_t;
- Result : Interfaces.C.int;
+ Result : Interfaces.C.int;
begin
Result := pthread_mutexattr_init (Attributes'Access);
@@ -318,7 +269,6 @@ package body System.Task_Primitives.Operations is
procedure Finalize_Lock (L : access Lock) is
Result : Interfaces.C.int;
-
begin
Result := pthread_mutex_destroy (L.L'Access);
pragma Assert (Result = 0);
@@ -326,7 +276,6 @@ package body System.Task_Primitives.Operations is
procedure Finalize_Lock (L : access RTS_Lock) is
Result : Interfaces.C.int;
-
begin
Result := pthread_mutex_destroy (L);
pragma Assert (Result = 0);
@@ -337,8 +286,7 @@ package body System.Task_Primitives.Operations is
----------------
procedure Write_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
- Result : Interfaces.C.int;
-
+ Result : Interfaces.C.int;
begin
L.Owner_Priority := Get_Priority (Self);
@@ -352,20 +300,24 @@ package body System.Task_Primitives.Operations is
Ceiling_Violation := False;
end Write_Lock;
- procedure Write_Lock (L : access RTS_Lock) is
+ procedure Write_Lock
+ (L : access RTS_Lock; Global_Lock : Boolean := False)
+ is
Result : Interfaces.C.int;
-
begin
- Result := pthread_mutex_lock (L);
- pragma Assert (Result = 0);
+ if not Single_Lock or else Global_Lock then
+ Result := pthread_mutex_lock (L);
+ pragma Assert (Result = 0);
+ end if;
end Write_Lock;
procedure Write_Lock (T : Task_ID) is
Result : Interfaces.C.int;
-
begin
- Result := pthread_mutex_lock (T.Common.LL.L'Access);
- pragma Assert (Result = 0);
+ if not Single_Lock then
+ Result := pthread_mutex_lock (T.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ end if;
end Write_Lock;
---------------
@@ -382,41 +334,48 @@ package body System.Task_Primitives.Operations is
------------
procedure Unlock (L : access Lock) is
- Result : Interfaces.C.int;
-
+ Result : Interfaces.C.int;
begin
Result := pthread_mutex_unlock (L.L'Access);
pragma Assert (Result = 0);
end Unlock;
- procedure Unlock (L : access RTS_Lock) is
+ procedure Unlock (L : access RTS_Lock; Global_Lock : Boolean := False) is
Result : Interfaces.C.int;
-
begin
- Result := pthread_mutex_unlock (L);
- pragma Assert (Result = 0);
+ if not Single_Lock or else Global_Lock then
+ Result := pthread_mutex_unlock (L);
+ pragma Assert (Result = 0);
+ end if;
end Unlock;
procedure Unlock (T : Task_ID) is
Result : Interfaces.C.int;
-
begin
- Result := pthread_mutex_unlock (T.Common.LL.L'Access);
- pragma Assert (Result = 0);
+ if not Single_Lock then
+ Result := pthread_mutex_unlock (T.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ end if;
end Unlock;
- -------------
- -- Sleep --
- -------------
+ -----------
+ -- Sleep --
+ -----------
- procedure Sleep (Self_ID : Task_ID;
- Reason : System.Tasking.Task_States) is
+ procedure Sleep
+ (Self_ID : Task_ID;
+ Reason : System.Tasking.Task_States)
+ is
Result : Interfaces.C.int;
-
begin
- pragma Assert (Self_ID = Self);
- Result := pthread_cond_wait (Self_ID.Common.LL.CV'Access,
- Self_ID.Common.LL.L'Access);
+ if Single_Lock then
+ Result := pthread_cond_wait
+ (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
+ else
+ Result := pthread_cond_wait
+ (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
+ end if;
+
-- EINTR is not considered a failure.
pragma Assert (Result = 0 or else Result = EINTR);
end Sleep;
@@ -425,10 +384,6 @@ package body System.Task_Primitives.Operations is
-- Timed_Sleep --
-----------------
- -- This is for use within the run-time system, so abort is
- -- assumed to be already deferred, and the caller should be
- -- holding its own ATCB lock.
-
procedure Timed_Sleep
(Self_ID : Task_ID;
Time : Duration;
@@ -441,6 +396,7 @@ package body System.Task_Primitives.Operations is
Abs_Time : Duration;
Request : aliased timespec;
Result : Interfaces.C.int;
+
begin
Timedout := True;
Yielded := False;
@@ -458,9 +414,16 @@ package body System.Task_Primitives.Operations is
exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
or else Self_ID.Pending_Priority_Change;
- Result := pthread_cond_timedwait
- (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access,
- Request'Access);
+ if Single_Lock then
+ Result := pthread_cond_timedwait
+ (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access,
+ Request'Access);
+
+ else
+ Result := pthread_cond_timedwait
+ (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access,
+ Request'Access);
+ end if;
exit when Abs_Time <= Monotonic_Clock;
@@ -479,10 +442,6 @@ package body System.Task_Primitives.Operations is
-- Timed_Delay --
-----------------
- -- This is for use in implementing delay statements, so
- -- we assume the caller is abort-deferred but is holding
- -- no locks.
-
procedure Timed_Delay
(Self_ID : Task_ID;
Time : Duration;
@@ -492,13 +451,18 @@ package body System.Task_Primitives.Operations is
Abs_Time : Duration;
Request : aliased timespec;
Result : Interfaces.C.int;
- begin
+ begin
-- Only the little window between deferring abort and
-- locking Self_ID is the reason we need to
-- check for pending abort and priority change below! :(
SSL.Abort_Defer.all;
+
+ if Single_Lock then
+ Lock_RTS;
+ end if;
+
Write_Lock (Self_ID);
if Mode = Relative then
@@ -520,8 +484,13 @@ package body System.Task_Primitives.Operations is
exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
- Result := pthread_cond_timedwait (Self_ID.Common.LL.CV'Access,
- Self_ID.Common.LL.L'Access, Request'Access);
+ if Single_Lock then
+ Result := pthread_cond_timedwait (Self_ID.Common.LL.CV'Access,
+ Single_RTS_Lock'Access, Request'Access);
+ else
+ Result := pthread_cond_timedwait (Self_ID.Common.LL.CV'Access,
+ Self_ID.Common.LL.L'Access, Request'Access);
+ end if;
exit when Abs_Time <= Monotonic_Clock;
@@ -534,6 +503,11 @@ package body System.Task_Primitives.Operations is
end if;
Unlock (Self_ID);
+
+ if Single_Lock then
+ Unlock_RTS;
+ end if;
+
Result := sched_yield;
SSL.Abort_Undefer.all;
end Timed_Delay;
@@ -567,7 +541,6 @@ package body System.Task_Primitives.Operations is
procedure Wakeup (T : Task_ID; Reason : System.Tasking.Task_States) is
Result : Interfaces.C.int;
-
begin
Result := pthread_cond_signal (T.Common.LL.CV'Access);
pragma Assert (Result = 0);
@@ -579,7 +552,6 @@ package body System.Task_Primitives.Operations is
procedure Yield (Do_Yield : Boolean := True) is
Result : Interfaces.C.int;
-
begin
if Do_Yield then
Result := sched_yield;
@@ -681,15 +653,17 @@ package body System.Task_Primitives.Operations is
Result := pthread_setspecific (ATCB_Key, To_Address (Self_ID));
pragma Assert (Result = 0);
- Lock_All_Tasks_List;
- for I in Known_Tasks'Range loop
- if Known_Tasks (I) = null then
- Known_Tasks (I) := Self_ID;
- Self_ID.Known_Tasks_Index := I;
+ Lock_RTS;
+
+ for J in Known_Tasks'Range loop
+ if Known_Tasks (J) = null then
+ Known_Tasks (J) := Self_ID;
+ Self_ID.Known_Tasks_Index := J;
exit;
end if;
end loop;
- Unlock_All_Tasks_List;
+
+ Unlock_RTS;
end Enter_Task;
--------------
@@ -701,55 +675,52 @@ package body System.Task_Primitives.Operations is
return new Ada_Task_Control_Block (Entry_Num);
end New_ATCB;
- ----------------------
- -- Initialize_TCB --
- ----------------------
+ --------------------
+ -- Initialize_TCB --
+ --------------------
procedure Initialize_TCB (Self_ID : Task_ID; Succeeded : out Boolean) is
Mutex_Attr : aliased pthread_mutexattr_t;
- Result : Interfaces.C.int;
- Cond_Attr : aliased pthread_condattr_t;
+ Result : Interfaces.C.int;
+ Cond_Attr : aliased pthread_condattr_t;
begin
- Result := pthread_mutexattr_init (Mutex_Attr'Access);
- pragma Assert (Result = 0 or else Result = ENOMEM);
+ if not Single_Lock then
+ Result := pthread_mutexattr_init (Mutex_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
- if Result /= 0 then
- Succeeded := False;
- return;
- end if;
+ if Result = 0 then
+ Result := pthread_mutex_init (Self_ID.Common.LL.L'Access,
+ Mutex_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+ end if;
- Result := pthread_mutex_init (Self_ID.Common.LL.L'Access,
- Mutex_Attr'Access);
- pragma Assert (Result = 0 or else Result = ENOMEM);
+ if Result /= 0 then
+ Succeeded := False;
+ return;
+ end if;
- if Result /= 0 then
- Succeeded := False;
- return;
+ Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
+ pragma Assert (Result = 0);
end if;
- Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
- pragma Assert (Result = 0);
-
Result := pthread_condattr_init (Cond_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
- if Result /= 0 then
- Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
- pragma Assert (Result = 0);
- Succeeded := False;
- return;
+ if Result = 0 then
+ Result := pthread_cond_init (Self_ID.Common.LL.CV'Access,
+ Cond_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
end if;
- Result := pthread_cond_init (Self_ID.Common.LL.CV'Access,
- Cond_Attr'Access);
- pragma Assert (Result = 0 or else Result = ENOMEM);
-
if Result = 0 then
Succeeded := True;
else
- Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
- pragma Assert (Result = 0);
+ if not Single_Lock then
+ Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ end if;
+
Succeeded := False;
end if;
@@ -834,8 +805,11 @@ package body System.Task_Primitives.Operations is
Unchecked_Deallocation (Ada_Task_Control_Block, Task_ID);
begin
- Result := pthread_mutex_destroy (T.Common.LL.L'Access);
- pragma Assert (Result = 0);
+ if not Single_Lock then
+ Result := pthread_mutex_destroy (T.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ end if;
+
Result := pthread_cond_destroy (T.Common.LL.CV'Access);
pragma Assert (Result = 0);
@@ -901,23 +875,23 @@ package body System.Task_Primitives.Operations is
return Environment_Task_ID;
end Environment_Task;
- -------------------------
- -- Lock_All_Tasks_List --
- -------------------------
+ --------------
+ -- Lock_RTS --
+ --------------
- procedure Lock_All_Tasks_List is
+ procedure Lock_RTS is
begin
- Write_Lock (All_Tasks_L'Access);
- end Lock_All_Tasks_List;
+ Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
+ end Lock_RTS;
- ---------------------------
- -- Unlock_All_Tasks_List --
- ---------------------------
+ ----------------
+ -- Unlock_RTS --
+ ----------------
- procedure Unlock_All_Tasks_List is
+ procedure Unlock_RTS is
begin
- Unlock (All_Tasks_L'Access);
- end Unlock_All_Tasks_List;
+ Unlock (Single_RTS_Lock'Access, Global_Lock => True);
+ end Unlock_RTS;
------------------
-- Suspend_Task --
@@ -955,7 +929,7 @@ package body System.Task_Primitives.Operations is
Environment_Task_ID := Environment_Task;
- Initialize_Lock (All_Tasks_L'Access, All_Tasks_Level);
+ Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
-- Initialize the lock used to synchronize chain of all ATCBs.
Enter_Task (Environment_Task);
@@ -985,7 +959,6 @@ package body System.Task_Primitives.Operations is
end do_nothing;
begin
-
declare
Result : Interfaces.C.int;
begin
@@ -998,5 +971,4 @@ begin
Result := pthread_key_create (ATCB_Key'Access, do_nothing'Access);
pragma Assert (Result = 0);
end;
-
end System.Task_Primitives.Operations;