summaryrefslogtreecommitdiff
path: root/gcc/ada/5staprop.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/5staprop.adb')
-rw-r--r--gcc/ada/5staprop.adb653
1 files changed, 272 insertions, 381 deletions
diff --git a/gcc/ada/5staprop.adb b/gcc/ada/5staprop.adb
index e23bd0163e5..588c0d3a0c7 100644
--- a/gcc/ada/5staprop.adb
+++ b/gcc/ada/5staprop.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2002, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2003, 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- --
@@ -101,9 +101,9 @@ package body System.Task_Primitives.Operations is
package SSL renames System.Soft_Links;
- ------------------
- -- Local Data --
- ------------------
+ ----------------
+ -- Local Data --
+ ----------------
-- The following are logically constants, but need to be initialized
-- at run time.
@@ -130,9 +130,9 @@ package body System.Task_Primitives.Operations is
-- using in error checking.
-- The following are internal configuration constants needed.
- ------------------------
- -- Priority Support --
- ------------------------
+ ----------------------
+ -- Priority Support --
+ ----------------------
Priority_Ceiling_Emulation : constant Boolean := True;
-- controls whether we emulate priority ceiling locking
@@ -153,9 +153,9 @@ package body System.Task_Primitives.Operations is
-- Hold priority info (Real_Time) initialized during the package
-- elaboration.
- -------------------------------------
- -- External Configuration Values --
- -------------------------------------
+ -----------------------------------
+ -- External Configuration Values --
+ -----------------------------------
Time_Slice_Val : Interfaces.C.long;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
@@ -166,51 +166,9 @@ package body System.Task_Primitives.Operations is
Dispatching_Policy : Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
- --------------------------------
- -- Foreign Threads Detection --
- --------------------------------
-
- -- The following are used to allow the Self function to
- -- automatically generate ATCB's for C threads that happen to call
- -- Ada procedure, which in turn happen to call the Ada run-time system.
-
- type Fake_ATCB;
- type Fake_ATCB_Ptr is access Fake_ATCB;
- type Fake_ATCB is record
- Stack_Base : Interfaces.C.unsigned := 0;
- -- A value of zero indicates the node is not in use.
- Next : Fake_ATCB_Ptr;
- Real_ATCB : aliased Ada_Task_Control_Block (0);
- end record;
-
- Fake_ATCB_List : Fake_ATCB_Ptr;
- -- A linear linked list.
- -- The list is protected by Single_RTS_Lock;
- -- Nodes are added to this list from the front.
- -- Once a node is added to this list, it is never removed.
-
- Fake_Task_Elaborated : aliased Boolean := True;
+ Foreign_Task_Elaborated : aliased Boolean := True;
-- Used to identified fake tasks (i.e., non-Ada Threads).
- Next_Fake_ATCB : Fake_ATCB_Ptr;
- -- Used to allocate one Fake_ATCB in advance. See comment in New_Fake_ATCB
-
- ------------
- -- Checks --
- ------------
-
- Check_Count : Integer := 0;
- Old_Owner : Task_ID;
- Lock_Count : Integer := 0;
- Unlock_Count : Integer := 0;
-
- function To_Lock_Ptr is
- new Unchecked_Conversion (RTS_Lock_Ptr, Lock_Ptr);
- function To_Task_ID is
- new Unchecked_Conversion (Owner_ID, Task_ID);
- function To_Owner_ID is
- new Unchecked_Conversion (Task_ID, Owner_ID);
-
-----------------------
-- Local Subprograms --
-----------------------
@@ -228,6 +186,9 @@ package body System.Task_Primitives.Operations is
(Sig : Signal;
Code : access siginfo_t;
Context : access ucontext_t);
+ -- Target-dependent binding of inter-thread Abort signal to
+ -- the raising of the Abort_Signal exception.
+ -- See also comments in 7staprop.adb
function To_thread_t is new Unchecked_Conversion
(Integer, System.OS_Interface.thread_t);
@@ -239,14 +200,6 @@ package body System.Task_Primitives.Operations is
function Thread_Body_Access is
new Unchecked_Conversion (System.Address, Thread_Body);
- function New_Fake_ATCB (Stack_Base : Interfaces.C.unsigned) return Task_ID;
- -- Allocate and Initialize a new ATCB. This code can safely be called from
- -- a foreign thread, as it doesn't access implicitly or explicitly
- -- "self" before having initialized the new ATCB.
- pragma Warnings (Off, New_Fake_ATCB);
- -- Disable warning on this function, since the Solaris x86 version does
- -- not use it.
-
------------
-- Checks --
------------
@@ -280,202 +233,88 @@ package body System.Task_Primitives.Operations is
function Check_Finalize_Lock (L : Lock_Ptr) return Boolean;
pragma Inline (Check_Finalize_Lock);
- -------------------
- -- New_Fake_ATCB --
- -------------------
-
- function New_Fake_ATCB (Stack_Base : Interfaces.C.unsigned)
- return Task_ID
- is
- Self_ID : Task_ID;
- P, Q : Fake_ATCB_Ptr;
- Succeeded : Boolean;
- Result : Interfaces.C.int;
-
- begin
- -- This section is ticklish.
- -- We dare not call anything that might require an ATCB, until
- -- we have the new ATCB in place.
- -- Note: we don't use Lock_RTS because we don't yet have an ATCB, and
- -- so can't pass the safety check.
-
- Result := mutex_lock (Single_RTS_Lock.L'Access);
- Q := null;
- P := Fake_ATCB_List;
-
- while P /= null loop
- if P.Stack_Base = 0 then
- Q := P;
- elsif thr_kill (P.Real_ATCB.Common.LL.Thread, 0) /= 0 then
- -- ????
- -- If a C thread that has dependent Ada tasks terminates
- -- abruptly, e.g. as a result of cancellation, any dependent
- -- tasks are likely to hang up in termination.
- P.Stack_Base := 0;
- Q := P;
- end if;
-
- P := P.Next;
- end loop;
-
- if Q = null then
-
- -- Create a new ATCB with zero entries.
-
- Self_ID := Next_Fake_ATCB.Real_ATCB'Access;
- Next_Fake_ATCB.Stack_Base := Stack_Base;
- Next_Fake_ATCB.Next := Fake_ATCB_List;
- Fake_ATCB_List := Next_Fake_ATCB;
- Next_Fake_ATCB := null;
-
- else
-
- -- Reuse an existing fake ATCB.
-
- Self_ID := Q.Real_ATCB'Access;
- Q.Stack_Base := Stack_Base;
- end if;
-
- -- Do the standard initializations
-
- System.Tasking.Initialize_ATCB
- (Self_ID, null, Null_Address, Null_Task, Fake_Task_Elaborated'Access,
- System.Priority'First, Task_Info.Unspecified_Task_Info, 0, Self_ID,
- Succeeded);
- pragma Assert (Succeeded);
-
- -- Record this as the Task_ID for the current thread.
-
- Self_ID.Common.LL.Thread := thr_self;
- Result := thr_setspecific (ATCB_Key, To_Address (Self_ID));
- pragma Assert (Result = 0);
-
- -- Finally, it is safe to use an allocator in this thread.
-
- if Next_Fake_ATCB = null then
- Next_Fake_ATCB := new Fake_ATCB;
- end if;
-
- Self_ID.Master_of_Task := 0;
- Self_ID.Master_Within := Self_ID.Master_of_Task + 1;
-
- for L in Self_ID.Entry_Calls'Range loop
- Self_ID.Entry_Calls (L).Self := Self_ID;
- Self_ID.Entry_Calls (L).Level := L;
- end loop;
+ --------------------
+ -- Local Packages --
+ --------------------
- Self_ID.Common.State := Runnable;
- Self_ID.Awake_Count := 1;
+ package Specific is
- -- Since this is not an ordinary Ada task, we will start out undeferred
+ procedure Initialize (Environment_Task : Task_ID);
+ pragma Inline (Initialize);
+ -- Initialize various data needed by this package.
- Self_ID.Deferral_Level := 0;
+ function Is_Valid_Task return Boolean;
+ pragma Inline (Is_Valid_Task);
+ -- Does executing thread have a TCB?
- -- Give the task a unique serial number.
+ procedure Set (Self_Id : Task_ID);
+ pragma Inline (Set);
+ -- Set the self id for the current task.
- Self_ID.Serial_Number := Next_Serial_Number;
- Next_Serial_Number := Next_Serial_Number + 1;
- pragma Assert (Next_Serial_Number /= 0);
-
- System.Soft_Links.Create_TSD (Self_ID.Common.Compiler_Data);
-
- -- ????
- -- The following call is commented out to avoid dependence on
- -- the System.Tasking.Initialization package.
+ function Self return Task_ID;
+ pragma Inline (Self);
+ -- Return a pointer to the Ada Task Control Block of the calling task.
- -- It seems that if we want Ada.Task_Attributes to work correctly
- -- for C threads we will need to raise the visibility of this soft
- -- link to System.Soft_Links.
+ end Specific;
- -- We are putting that off until this new functionality is otherwise
- -- stable.
+ package body Specific is separate;
+ -- The body of this package is target specific.
- -- System.Tasking.Initialization.Initialize_Attributes_Link.all (T);
+ ---------------------------------
+ -- Support for foreign threads --
+ ---------------------------------
- -- Must not unlock until Next_ATCB is again allocated.
+ function Register_Foreign_Thread (Thread : Thread_Id) return Task_ID;
+ -- Allocate and Initialize a new ATCB for the current Thread.
- 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;
+ function Register_Foreign_Thread
+ (Thread : Thread_Id) return Task_ID is separate;
- Result := mutex_unlock (Single_RTS_Lock.L'Access);
+ ------------
+ -- Checks --
+ ------------
- -- We cannot use Unlock_RTS because we did not use Write_Lock, and so
- -- would not pass the checks.
+ Check_Count : Integer := 0;
+ Old_Owner : Task_ID;
+ Lock_Count : Integer := 0;
+ Unlock_Count : Integer := 0;
- return Self_ID;
- end New_Fake_ATCB;
+ function To_Lock_Ptr is
+ new Unchecked_Conversion (RTS_Lock_Ptr, Lock_Ptr);
+ function To_Task_ID is
+ new Unchecked_Conversion (Owner_ID, Task_ID);
+ function To_Owner_ID is
+ new Unchecked_Conversion (Task_ID, Owner_ID);
-------------------
-- 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 longjmp out of
- -- a signal handler. (See below.)
-
- -- procedure Raise_Abort_Signal is
- -- begin
- -- raise Standard'Abort_Signal;
- -- end if;
-
- -- ???
- -- The comments above need revising. They are partly obsolete.
-
procedure Abort_Handler
(Sig : Signal;
Code : access siginfo_t;
Context : access ucontext_t)
is
+ pragma Unreferenced (Sig);
+ pragma Unreferenced (Code);
+ pragma Unreferenced (Context);
+
Self_ID : 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:
+ -- It is not safe to raise an exception when using ZCX and the GCC
+ -- exception handling mechanism.
+
+ if ZCX_By_Default and then GCC_ZCX_Support then
+ return;
+ end if;
if Self_ID.Deferral_Level = 0
and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
and then not Self_ID.Aborting
then
- -- You can comment the following out,
- -- to make all aborts synchronous, for debugging.
-
Self_ID.Aborting := True;
-- Make sure signals used for RTS internal purpose are unmasked
@@ -485,23 +324,7 @@ package body System.Task_Primitives.Operations is
pragma Assert (Result = 0);
raise Standard'Abort_Signal;
-
- -- ?????
- -- Must be certain that the implementation of "raise"
- -- does not make any OS/thread calls, or at least that
- -- if it makes any, they are safe for interruption by
- -- async. signals.
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;
-------------------
@@ -512,6 +335,9 @@ package body System.Task_Primitives.Operations is
-- bottom of a thread stack, so nothing is needed.
procedure Stack_Guard (T : ST.Task_ID; On : Boolean) is
+ pragma Unreferenced (T);
+ pragma Unreferenced (On);
+
begin
null;
end Stack_Guard;
@@ -525,11 +351,144 @@ package body System.Task_Primitives.Operations is
return T.Common.LL.Thread;
end Get_Thread_Id;
- -----------
- -- Self --
- -----------
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize (Environment_Task : ST.Task_ID) is
+ act : aliased struct_sigaction;
+ old_act : aliased struct_sigaction;
+ Tmp_Set : aliased sigset_t;
+ Result : Interfaces.C.int;
+
+ procedure Configure_Processors;
+ -- Processors configuration
+ -- The user can specify a processor which the program should run
+ -- on to emulate a single-processor system. This can be easily
+ -- done by setting environment variable GNAT_PROCESSOR to one of
+ -- the following :
+ --
+ -- -2 : use the default configuration (run the program on all
+ -- available processors) - this is the same as having
+ -- GNAT_PROCESSOR unset
+ -- -1 : let the RTS choose one processor and run the program on
+ -- that processor
+ -- 0 .. Last_Proc : run the program on the specified processor
+ --
+ -- Last_Proc is equal to the value of the system variable
+ -- _SC_NPROCESSORS_CONF, minus one.
+
+ procedure Configure_Processors is
+ Proc_Acc : constant GNAT.OS_Lib.String_Access :=
+ GNAT.OS_Lib.Getenv ("GNAT_PROCESSOR");
+ Proc : aliased processorid_t; -- User processor #
+ Last_Proc : processorid_t; -- Last processor #
+
+ begin
+ if Proc_Acc.all'Length /= 0 then
+ -- Environment variable is defined
+
+ Last_Proc := Num_Procs - 1;
+
+ if Last_Proc /= -1 then
+ Proc := processorid_t'Value (Proc_Acc.all);
+
+ if Proc <= -2 or else Proc > Last_Proc then
+ -- Use the default configuration
+ null;
+ elsif Proc = -1 then
+ -- Choose a processor
+
+ Result := 0;
+
+ while Proc < Last_Proc loop
+ Proc := Proc + 1;
+ Result := p_online (Proc, PR_STATUS);
+ exit when Result = PR_ONLINE;
+ end loop;
+
+ pragma Assert (Result = PR_ONLINE);
+ Result := processor_bind (P_PID, P_MYID, Proc, null);
+ pragma Assert (Result = 0);
+
+ else
+ -- Use user processor
+
+ Result := processor_bind (P_PID, P_MYID, Proc, null);
+ pragma Assert (Result = 0);
+ end if;
+ end if;
+ end if;
+
+ exception
+ when Constraint_Error =>
+
+ -- Illegal environment variable GNAT_PROCESSOR - ignored
+
+ null;
+ end Configure_Processors;
+
+ function State (Int : System.Interrupt_Management.Interrupt_ID)
+ return Character;
+ pragma Import (C, State, "__gnat_get_interrupt_state");
+ -- Get interrupt state. Defined in a-init.c
+ -- The input argument is the interrupt number,
+ -- and the result is one of the following:
- function Self return Task_ID is separate;
+ Default : constant Character := 's';
+ -- 'n' this interrupt not set by any Interrupt_State pragma
+ -- 'u' Interrupt_State pragma set state to User
+ -- 'r' Interrupt_State pragma set state to Runtime
+ -- 's' Interrupt_State pragma set state to System (use "default"
+ -- system handler)
+
+ -- Start of processing for Initialize
+
+ begin
+ Environment_Task_ID := Environment_Task;
+
+ -- This is done in Enter_Task, but this is too late for the
+ -- Environment Task, since we need to call Self in Check_Locks when
+ -- the run time is compiled with assertions on.
+
+ Specific.Initialize (Environment_Task);
+
+ -- Initialize the lock used to synchronize chain of all ATCBs.
+
+ Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
+
+ Enter_Task (Environment_Task);
+
+ -- Install the abort-signal handler
+
+ if State (System.Interrupt_Management.Abort_Task_Interrupt)
+ /= Default
+ then
+ -- Set sa_flags to SA_NODEFER so that during the handler execution
+ -- we do not change the Signal_Mask to be masked for the Abort_Signal
+ -- This is a temporary fix to the problem that the Signal_Mask is
+ -- not restored after the exception (longjmp) from the handler.
+ -- The right fix should be made in sigsetjmp so that we save
+ -- the Signal_Set and restore it after a longjmp.
+ -- In that case, this field should be changed back to 0. ???
+
+ act.sa_flags := 16;
+
+ act.sa_handler := Abort_Handler'Address;
+ Result := sigemptyset (Tmp_Set'Access);
+ pragma Assert (Result = 0);
+ act.sa_mask := Tmp_Set;
+
+ Result :=
+ sigaction (
+ Signal (System.Interrupt_Management.Abort_Task_Interrupt),
+ act'Unchecked_Access,
+ old_act'Unchecked_Access);
+ pragma Assert (Result = 0);
+ end if;
+
+ Configure_Processors;
+ end Initialize;
---------------------
-- Initialize_Lock --
@@ -646,9 +605,11 @@ package body System.Task_Primitives.Operations is
end Write_Lock;
procedure Write_Lock
- (L : access RTS_Lock; Global_Lock : Boolean := False)
+ (L : access RTS_Lock;
+ Global_Lock : Boolean := False)
is
Result : Interfaces.C.int;
+
begin
if not Single_Lock or else Global_Lock then
pragma Assert (Check_Lock (To_Lock_Ptr (RTS_Lock_Ptr (L))));
@@ -660,6 +621,7 @@ package body System.Task_Primitives.Operations is
procedure Write_Lock (T : Task_ID) is
Result : Interfaces.C.int;
+
begin
if not Single_Lock then
pragma Assert (Check_Lock (To_Lock_Ptr (T.Common.LL.L'Access)));
@@ -684,6 +646,7 @@ package body System.Task_Primitives.Operations is
procedure Unlock (L : access Lock) is
Result : Interfaces.C.int;
+
begin
pragma Assert (Check_Unlock (Lock_Ptr (L)));
@@ -707,6 +670,7 @@ package body System.Task_Primitives.Operations is
procedure Unlock (L : access RTS_Lock; Global_Lock : Boolean := False) is
Result : Interfaces.C.int;
+
begin
if not Single_Lock or else Global_Lock then
pragma Assert (Check_Unlock (To_Lock_Ptr (RTS_Lock_Ptr (L))));
@@ -717,6 +681,7 @@ package body System.Task_Primitives.Operations is
procedure Unlock (T : Task_ID) is
Result : Interfaces.C.int;
+
begin
if not Single_Lock then
pragma Assert (Check_Unlock (To_Lock_Ptr (T.Common.LL.L'Access)));
@@ -776,15 +741,23 @@ package body System.Task_Primitives.Operations is
end if;
end Yield;
+ -----------
+ -- Self ---
+ -----------
+
+ function Self return Task_ID renames Specific.Self;
+
------------------
-- Set_Priority --
------------------
procedure Set_Priority
- (T : Task_ID;
- Prio : System.Any_Priority;
+ (T : Task_ID;
+ Prio : System.Any_Priority;
Loss_Of_Inheritance : Boolean := False)
is
+ pragma Unreferenced (Loss_Of_Inheritance);
+
Result : Interfaces.C.int;
Param : aliased struct_pcparms;
@@ -885,8 +858,7 @@ package body System.Task_Primitives.Operations is
end if;
end if;
- Result := thr_setspecific (ATCB_Key, To_Address (Self_ID));
- pragma Assert (Result = 0);
+ Specific.Set (Self_ID);
-- We need the above code even if we do direct fetch of Task_ID in Self
-- for the main task on Sun, x86 Solaris and for gcc 2.7.2.
@@ -913,12 +885,33 @@ package body System.Task_Primitives.Operations is
return new Ada_Task_Control_Block (Entry_Num);
end New_ATCB;
+ -------------------
+ -- Is_Valid_Task --
+ -------------------
+
+ function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
+
+ -----------------------------
+ -- Register_Foreign_Thread --
+ -----------------------------
+
+ function Register_Foreign_Thread return Task_ID is
+
+ begin
+ if Is_Valid_Task then
+ return Self;
+ else
+ return Register_Foreign_Thread (thr_self);
+ end if;
+ end Register_Foreign_Thread;
+
--------------------
-- Initialize_TCB --
--------------------
procedure Initialize_TCB (Self_ID : Task_ID; Succeeded : out Boolean) is
Result : Interfaces.C.int := 0;
+
begin
-- Give the task a unique serial number.
@@ -964,6 +957,8 @@ package body System.Task_Primitives.Operations is
Priority : System.Any_Priority;
Succeeded : out Boolean)
is
+ pragma Unreferenced (Priority);
+
Result : Interfaces.C.int;
Adjusted_Stack_Size : Interfaces.C.size_t;
Opts : Interfaces.C.int := THR_DETACHED;
@@ -976,6 +971,7 @@ package body System.Task_Primitives.Operations is
-- actual use.
use System.Task_Info;
+
begin
if Stack_Size = System.Parameters.Unspecified_Size then
Adjusted_Stack_Size :=
@@ -996,7 +992,6 @@ package body System.Task_Primitives.Operations is
-- All tasks in RTS will have All_Tasks_Mask initially.
if T.Common.Task_Info /= null then
-
if T.Common.Task_Info.New_LWP then
Opts := Opts + THR_NEW_LWP;
end if;
@@ -1031,6 +1026,7 @@ package body System.Task_Primitives.Operations is
procedure Finalize_TCB (T : Task_ID) is
Result : Interfaces.C.int;
Tmp : Task_ID := T;
+ Is_Self : constant Boolean := T = Self;
procedure Free is new
Unchecked_Deallocation (Ada_Task_Control_Block, Task_ID);
@@ -1051,6 +1047,11 @@ package body System.Task_Primitives.Operations is
end if;
Free (Tmp);
+
+ if Is_Self then
+ Specific.Set (null);
+ end if;
+
end Finalize_TCB;
---------------
@@ -1063,7 +1064,7 @@ package body System.Task_Primitives.Operations is
procedure Exit_Task is
begin
- thr_exit (System.Null_Address);
+ Specific.Set (null);
end Exit_Task;
----------------
@@ -1091,6 +1092,7 @@ package body System.Task_Primitives.Operations is
Reason : Task_States)
is
Result : Interfaces.C.int;
+
begin
pragma Assert (Check_Sleep (Reason));
@@ -1236,7 +1238,9 @@ package body System.Task_Primitives.Operations is
exit when Abs_Time <= Monotonic_Clock;
if Result = 0 or Result = EINTR then
- -- somebody may have called Wakeup for us
+
+ -- Somebody may have called Wakeup for us
+
Timedout := False;
exit;
end if;
@@ -1344,6 +1348,7 @@ package body System.Task_Primitives.Operations is
Reason : Task_States)
is
Result : Interfaces.C.int;
+
begin
pragma Assert (Check_Wakeup (T, Reason));
Result := cond_signal (T.Common.LL.CV'Access);
@@ -1386,7 +1391,7 @@ package body System.Task_Primitives.Operations is
----------------
function Check_Lock (L : Lock_Ptr) return Boolean is
- Self_ID : Task_ID := Self;
+ Self_ID : constant Task_ID := Self;
P : Lock_Ptr;
begin
@@ -1475,6 +1480,8 @@ package body System.Task_Primitives.Operations is
-----------------
function Check_Sleep (Reason : Task_States) return Boolean is
+ pragma Unreferenced (Reason);
+
Self_ID : Task_ID := Self;
P : Lock_Ptr;
@@ -1519,6 +1526,8 @@ package body System.Task_Primitives.Operations is
Reason : Task_States)
return Boolean
is
+ pragma Unreferenced (Reason);
+
Self_ID : Task_ID := Self;
P : Lock_Ptr;
@@ -1553,7 +1562,7 @@ package body System.Task_Primitives.Operations is
Reason : Task_States)
return Boolean
is
- Self_ID : Task_ID := Self;
+ Self_ID : constant Task_ID := Self;
begin
-- Is caller holding T's lock?
@@ -1625,7 +1634,8 @@ package body System.Task_Primitives.Operations is
--------------------
function Check_Finalize_Lock (L : Lock_Ptr) return Boolean is
- Self_ID : Task_ID := Self;
+ Self_ID : constant Task_ID := Self;
+
begin
-- Check that caller is abort-deferred
@@ -1717,7 +1727,9 @@ package body System.Task_Primitives.Operations is
function Suspend_Task
(T : ST.Task_ID;
- Thread_Self : Thread_Id) return Boolean is
+ Thread_Self : Thread_Id)
+ return Boolean
+ is
begin
if T.Common.LL.Thread /= Thread_Self then
return thr_suspend (T.Common.LL.Thread) = 0;
@@ -1732,7 +1744,9 @@ package body System.Task_Primitives.Operations is
function Resume_Task
(T : ST.Task_ID;
- Thread_Self : Thread_Id) return Boolean is
+ Thread_Self : Thread_Id)
+ return Boolean
+ is
begin
if T.Common.LL.Thread /= Thread_Self then
return thr_continue (T.Common.LL.Thread) = 0;
@@ -1741,135 +1755,12 @@ package body System.Task_Primitives.Operations is
end if;
end Resume_Task;
- ----------------
- -- Initialize --
- ----------------
-
- procedure Initialize (Environment_Task : ST.Task_ID) is
- act : aliased struct_sigaction;
- old_act : aliased struct_sigaction;
- Tmp_Set : aliased sigset_t;
- Result : Interfaces.C.int;
-
- procedure Configure_Processors;
- -- Processors configuration
- -- The user can specify a processor which the program should run
- -- on to emulate a single-processor system. This can be easily
- -- done by setting environment variable GNAT_PROCESSOR to one of
- -- the following :
- --
- -- -2 : use the default configuration (run the program on all
- -- available processors) - this is the same as having
- -- GNAT_PROCESSOR unset
- -- -1 : let the RTS choose one processor and run the program on
- -- that processor
- -- 0 .. Last_Proc : run the program on the specified processor
- --
- -- Last_Proc is equal to the value of the system variable
- -- _SC_NPROCESSORS_CONF, minus one.
-
- procedure Configure_Processors is
- Proc_Acc : constant GNAT.OS_Lib.String_Access :=
- GNAT.OS_Lib.Getenv ("GNAT_PROCESSOR");
- Proc : aliased processorid_t; -- User processor #
- Last_Proc : processorid_t; -- Last processor #
-
- begin
- if Proc_Acc.all'Length /= 0 then
- -- Environment variable is defined
-
- Last_Proc := Num_Procs - 1;
-
- if Last_Proc /= -1 then
- Proc := processorid_t'Value (Proc_Acc.all);
-
- if Proc <= -2 or else Proc > Last_Proc then
- -- Use the default configuration
- null;
- elsif Proc = -1 then
- -- Choose a processor
-
- Result := 0;
-
- while Proc < Last_Proc loop
- Proc := Proc + 1;
- Result := p_online (Proc, PR_STATUS);
- exit when Result = PR_ONLINE;
- end loop;
-
- pragma Assert (Result = PR_ONLINE);
- Result := processor_bind (P_PID, P_MYID, Proc, null);
- pragma Assert (Result = 0);
-
- else
- -- Use user processor
-
- Result := processor_bind (P_PID, P_MYID, Proc, null);
- pragma Assert (Result = 0);
- end if;
- end if;
- end if;
-
- exception
- when Constraint_Error =>
- -- Illegal environment variable GNAT_PROCESSOR - ignored
- null;
- end Configure_Processors;
-
- -- Start of processing for Initialize
-
- begin
- Environment_Task_ID := Environment_Task;
-
- -- This is done in Enter_Task, but this is too late for the
- -- Environment Task, since we need to call Self in Check_Locks when
- -- the run time is compiled with assertions on.
-
- Result := thr_setspecific (ATCB_Key, To_Address (Environment_Task));
- pragma Assert (Result = 0);
-
- -- Initialize the lock used to synchronize chain of all ATCBs.
-
- Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
-
- Enter_Task (Environment_Task);
-
- -- Install the abort-signal handler
-
- -- Set sa_flags to SA_NODEFER so that during the handler execution
- -- we do not change the Signal_Mask to be masked for the Abort_Signal.
- -- This is a temporary fix to the problem that the Signal_Mask is
- -- not restored after the exception (longjmp) from the handler.
- -- The right fix should be made in sigsetjmp so that we save
- -- the Signal_Set and restore it after a longjmp.
- -- In that case, this field should be changed back to 0. ???
-
- act.sa_flags := 16;
-
- act.sa_handler := Abort_Handler'Address;
- Result := sigemptyset (Tmp_Set'Access);
- pragma Assert (Result = 0);
- act.sa_mask := Tmp_Set;
-
- Result :=
- sigaction (
- Signal (System.Interrupt_Management.Abort_Task_Interrupt),
- act'Unchecked_Access,
- old_act'Unchecked_Access);
- pragma Assert (Result = 0);
-
- Configure_Processors;
-
- -- Create a free ATCB for use on the Fake_ATCB_List.
-
- Next_Fake_ATCB := new Fake_ATCB;
- end Initialize;
-
-- Package elaboration
begin
declare
Result : Interfaces.C.int;
+
begin
-- Mask Environment task for all signals. The original mask of the
-- Environment task will be recovered by Interrupt_Server task