aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/5itaprop.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/5itaprop.adb')
-rw-r--r--gcc/ada/5itaprop.adb251
1 files changed, 149 insertions, 102 deletions
diff --git a/gcc/ada/5itaprop.adb b/gcc/ada/5itaprop.adb
index b1edfd0..56797f6 100644
--- a/gcc/ada/5itaprop.adb
+++ b/gcc/ada/5itaprop.adb
@@ -6,9 +6,9 @@
-- --
-- B o d y --
-- --
--- $Revision: 1.2 $
+-- $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,8 +29,7 @@
-- 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). --
-- --
------------------------------------------------------------------------------
@@ -112,11 +111,10 @@ package body System.Task_Primitives.Operations is
-- The followings are logically constants, but need to be initialized
-- at run time.
- 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.
@@ -186,6 +184,29 @@ package body System.Task_Primitives.Operations is
function To_pthread_t is new Unchecked_Conversion
(Integer, System.OS_Interface.pthread_t);
+ --------------------
+ -- Local Packages --
+ --------------------
+
+ package Specific is
+
+ procedure Initialize (Environment_Task : Task_ID);
+ pragma Inline (Initialize);
+ -- Initialize various data needed by this package.
+
+ procedure Set (Self_Id : Task_ID);
+ pragma Inline (Set);
+ -- Set the self id for the current task.
+
+ function Self return Task_ID;
+ pragma Inline (Self);
+ -- Return a pointer to the Ada Task Control Block of the calling task.
+
+ end Specific;
+
+ package body Specific is separate;
+ -- The body of this package is target specific.
+
-------------------
-- Abort_Handler --
-------------------
@@ -297,9 +318,27 @@ package body System.Task_Primitives.Operations is
end if;
end Abort_Handler;
- -------------------
- -- Stack_Guard --
- -------------------
+ --------------
+ -- Lock_RTS --
+ --------------
+
+ procedure Lock_RTS is
+ begin
+ Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
+ end Lock_RTS;
+
+ ----------------
+ -- Unlock_RTS --
+ ----------------
+
+ procedure Unlock_RTS is
+ begin
+ Unlock (Single_RTS_Lock'Access, Global_Lock => True);
+ end Unlock_RTS;
+
+ -----------------
+ -- Stack_Guard --
+ -----------------
-- The underlying thread system extends the memory (up to 2MB) when
-- needed.
@@ -322,14 +361,7 @@ package body System.Task_Primitives.Operations is
-- Self --
----------
- function Self return Task_ID is
- Result : System.Address;
-
- begin
- Result := pthread_getspecific (ATCB_Key);
- pragma Assert (Result /= System.Null_Address);
- return To_Task_ID (Result);
- end Self;
+ function Self return Task_ID renames Specific.Self;
---------------------
-- Initialize_Lock --
@@ -337,7 +369,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.
@@ -401,7 +433,6 @@ package body System.Task_Primitives.Operations is
procedure Write_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
Result : Interfaces.C.int;
-
begin
if Priority_Ceiling_Emulation then
declare
@@ -427,20 +458,24 @@ package body System.Task_Primitives.Operations is
end if;
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;
---------------
@@ -458,7 +493,6 @@ package body System.Task_Primitives.Operations is
procedure Unlock (L : access Lock) is
Result : Interfaces.C.int;
-
begin
if Priority_Ceiling_Emulation then
declare
@@ -476,39 +510,44 @@ package body System.Task_Primitives.Operations is
end if;
end Unlock;
- procedure Unlock (L : access RTS_Lock) is
+ procedure Unlock (L : access RTS_Lock; Global_Lock : Boolean := False) is
Result : Interfaces.C.int;
- -- Beware of any changes to this that might
- -- require access to the ATCB after the mutex is unlocked.
- -- This is the last operation performed by a task
- -- before it allows its ATCB to be deallocated, so it
- -- MUST NOT refer to the ATCB.
-
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;
@@ -550,9 +589,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;
@@ -591,6 +637,11 @@ package body System.Task_Primitives.Operations is
-- 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
@@ -612,8 +663,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;
@@ -626,6 +682,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;
@@ -734,23 +795,22 @@ package body System.Task_Primitives.Operations is
----------------
procedure Enter_Task (Self_ID : Task_ID) is
- Result : Interfaces.C.int;
-
begin
Self_ID.Common.LL.Thread := pthread_self;
- Result := pthread_setspecific (ATCB_Key, To_Address (Self_ID));
- pragma Assert (Result = 0);
+ Specific.Set (Self_ID);
- 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;
--------------
@@ -778,13 +838,15 @@ package body System.Task_Primitives.Operations is
Self_ID.Common.LL.Thread := To_pthread_t (-1);
- Result := pthread_mutex_init (Self_ID.Common.LL.L'Access,
- Mutex_Attr'Access);
- pragma Assert (Result = 0 or else Result = ENOMEM);
+ if not Single_Lock then
+ 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;
+ if Result /= 0 then
+ Succeeded := False;
+ return;
+ end if;
end if;
Result := pthread_cond_init (Self_ID.Common.LL.CV'Access,
@@ -794,13 +856,13 @@ package body System.Task_Primitives.Operations is
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;
-
- Result := pthread_condattr_destroy (Cond_Attr'Access);
- pragma Assert (Result = 0);
end Initialize_TCB;
-----------------
@@ -865,13 +927,18 @@ 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);
+
if T.Known_Tasks_Index /= -1 then
Known_Tasks (T.Known_Tasks_Index) := null;
end if;
+
Free (Tmp);
end Finalize_TCB;
@@ -927,24 +994,6 @@ package body System.Task_Primitives.Operations is
return Environment_Task_ID;
end Environment_Task;
- -------------------------
- -- Lock_All_Tasks_List --
- -------------------------
-
- procedure Lock_All_Tasks_List is
- begin
- Write_Lock (All_Tasks_L'Access);
- end Lock_All_Tasks_List;
-
- ---------------------------
- -- Unlock_All_Tasks_List --
- ---------------------------
-
- procedure Unlock_All_Tasks_List is
- begin
- Unlock (All_Tasks_L'Access);
- end Unlock_All_Tasks_List;
-
------------------
-- Suspend_Task --
------------------
@@ -994,8 +1043,10 @@ package body System.Task_Primitives.Operations is
Result := pthread_condattr_init (Cond_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
- Initialize_Lock (All_Tasks_L'Access, All_Tasks_Level);
- -- Initialize the lock used to synchronize chain of all ATCBs.
+ Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
+ -- Initialize the global RTS lock
+
+ Specific.Initialize (Environment_Task);
Enter_Task (Environment_Task);
@@ -1038,9 +1089,5 @@ begin
pragma Assert (Result = 0);
end if;
end loop;
-
- Result := pthread_key_create (ATCB_Key'Access, null);
- pragma Assert (Result = 0);
end;
-
end System.Task_Primitives.Operations;