-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2010, 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- --
with System.Interrupt_Management;
with System.OS_Primitives;
with System.Stack_Checking.Operations;
+with System.Multiprocessors;
with System.Soft_Links;
-- We use System.Soft_Links instead of System.Tasking.Initialization
begin
pragma Assert (Self_ID = Self);
- 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;
+ Result :=
+ pthread_cond_wait
+ (cond => Self_ID.Common.LL.CV'Access,
+ mutex => (if Single_Lock
+ then Single_RTS_Lock'Access
+ else Self_ID.Common.LL.L'Access));
-- EINTR is not considered a failure
Timedout := True;
Yielded := False;
- if Mode = Relative then
- Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
- else
- Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
- end if;
+ Abs_Time :=
+ (if Mode = Relative
+ then Duration'Min (Time, Max_Sensible_Delay) + Check_Time
+ else Duration'Min (Check_Time + Max_Sensible_Delay, Time));
if Abs_Time > Check_Time then
Request := To_Timespec (Abs_Time);
loop
exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
- 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;
+ Result :=
+ pthread_cond_timedwait
+ (cond => Self_ID.Common.LL.CV'Access,
+ mutex => (if Single_Lock
+ then Single_RTS_Lock'Access
+ else Self_ID.Common.LL.L'Access),
+ abstime => Request'Access);
Check_Time := Monotonic_Clock;
exit when Abs_Time <= Check_Time or else Check_Time < Base_Time;
Write_Lock (Self_ID);
- if Mode = Relative then
- Abs_Time := Time + Check_Time;
- else
- Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
- end if;
+ Abs_Time :=
+ (if Mode = Relative
+ then Time + Check_Time
+ else Duration'Min (Check_Time + Max_Sensible_Delay, Time));
if Abs_Time > Check_Time then
Request := To_Timespec (Abs_Time);
loop
exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
- 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;
+ Result :=
+ pthread_cond_timedwait
+ (cond => Self_ID.Common.LL.CV'Access,
+ mutex => (if Single_Lock
+ then Single_RTS_Lock'Access
+ else Self_ID.Common.LL.L'Access),
+ abstime => Request'Access);
Check_Time := Monotonic_Clock;
exit when Abs_Time <= Check_Time or else Check_Time < Base_Time;
Specific.Set (Self_ID);
- if Use_Alternate_Stack then
+ if Use_Alternate_Stack
+ and then Self_ID.Common.Task_Alternate_Stack /= Null_Address
+ then
declare
Stack : aliased stack_t;
Result : Interfaces.C.int;
Adjusted_Stack_Size : Interfaces.C.size_t;
Result : Interfaces.C.int;
+ use type System.Multiprocessors.CPU_Range;
+
begin
Adjusted_Stack_Size :=
Interfaces.C.size_t (Stack_Size + Alternate_Stack_Size);
(Attributes'Access, PTHREAD_CREATE_DETACHED);
pragma Assert (Result = 0);
+ -- Set the required attributes for the creation of the thread
+
+ -- Note: Previously, we called pthread_setaffinity_np (after thread
+ -- creation but before thread activation) to set the affinity but it was
+ -- not behaving as expected. Setting the required attributes for the
+ -- creation of the thread works correctly and it is more appropriate.
+
+ -- Do nothing if required support not provided by the operating system
+
+ if pthread_attr_setaffinity_np'Address = System.Null_Address then
+ null;
+
+ -- Support is available
+
+ elsif T.Common.Base_CPU /= System.Multiprocessors.Not_A_Specific_CPU then
+ declare
+ CPU_Set : aliased cpu_set_t := (bits => (others => False));
+ begin
+ CPU_Set.bits (Integer (T.Common.Base_CPU)) := True;
+ Result :=
+ pthread_attr_setaffinity_np
+ (Attributes'Access,
+ CPU_SETSIZE / 8,
+ CPU_Set'Access);
+ pragma Assert (Result = 0);
+ end;
+
+ -- Handle Task_Info
+
+ elsif T.Common.Task_Info /= null
+ and then T.Common.Task_Info.CPU_Affinity /= Task_Info.Any_CPU
+ then
+ Result :=
+ pthread_attr_setaffinity_np
+ (Attributes'Access,
+ CPU_SETSIZE / 8,
+ T.Common.Task_Info.CPU_Affinity'Access);
+ pragma Assert (Result = 0);
+ end if;
+
-- Since the initial signal mask of a thread is inherited from the
-- creator, and the Environment task has all its signals masked, we
-- do not need to manipulate caller's signal mask at this point.
Succeeded := True;
- -- Handle Task_Info
-
- if T.Common.Task_Info /= null then
- if T.Common.Task_Info.CPU_Affinity /= Task_Info.Any_CPU then
- Result :=
- pthread_setaffinity_np
- (T.Common.LL.Thread,
- CPU_SETSIZE / 8,
- T.Common.Task_Info.CPU_Affinity'Access);
- pragma Assert (Result = 0);
- end if;
- end if;
-
Result := pthread_attr_destroy (Attributes'Access);
pragma Assert (Result = 0);
SSL.Abort_Undefer.all;
raise Program_Error;
+
else
-- Suspend the task if the state is False. Otherwise, the task
-- continues its execution, and the state of the suspension object
-- Loop in case pthread_cond_wait returns earlier than expected
-- (e.g. in case of EINTR caused by a signal). This should not
-- happen with the current Linux implementation of pthread, but
- -- POSIX does not guarantee it, so this may change in the
- -- future.
+ -- POSIX does not guarantee it so this may change in future.
Result := pthread_cond_wait (S.CV'Access, S.L'Access);
pragma Assert (Result = 0 or else Result = EINTR);
-- 's' Interrupt_State pragma set state to System (use "default"
-- system handler)
+ use type System.Multiprocessors.CPU_Range;
+
begin
Environment_Task_Id := Environment_Task;
pragma Assert (Result = 0);
Abort_Handler_Installed := True;
end if;
+
+ -- pragma CPU for the environment task
+
+ if pthread_setaffinity_np'Address /= System.Null_Address
+ and then Environment_Task.Common.Base_CPU /=
+ System.Multiprocessors.Not_A_Specific_CPU
+ then
+ declare
+ CPU_Set : aliased cpu_set_t := (bits => (others => False));
+ begin
+ CPU_Set.bits (Integer (Environment_Task.Common.Base_CPU)) := True;
+ Result :=
+ pthread_setaffinity_np
+ (Environment_Task.Common.LL.Thread,
+ CPU_SETSIZE / 8,
+ CPU_Set'Access);
+ pragma Assert (Result = 0);
+ end;
+ end if;
end Initialize;
end System.Task_Primitives.Operations;