OSDN Git Service

2010-10-22 Ben Brosgol <brosgol@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-taprop-linux.adb
index 0f0773c..db6ac9f 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                  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- --
@@ -48,6 +48,7 @@ with System.Tasking.Debug;
 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
@@ -426,15 +427,12 @@ package body System.Task_Primitives.Operations is
    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
 
@@ -469,11 +467,10 @@ package body System.Task_Primitives.Operations is
       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);
@@ -481,20 +478,13 @@ package body System.Task_Primitives.Operations is
          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;
@@ -539,11 +529,10 @@ package body System.Task_Primitives.Operations is
 
       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);
@@ -552,17 +541,13 @@ package body System.Task_Primitives.Operations is
          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;
@@ -733,7 +718,9 @@ package body System.Task_Primitives.Operations is
 
       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;
@@ -833,6 +820,8 @@ package body System.Task_Primitives.Operations is
       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);
@@ -855,6 +844,46 @@ package body System.Task_Primitives.Operations is
           (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.
@@ -877,19 +906,6 @@ package body System.Task_Primitives.Operations is
 
       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);
 
@@ -1104,6 +1120,7 @@ package body System.Task_Primitives.Operations is
          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
@@ -1118,8 +1135,7 @@ package body System.Task_Primitives.Operations is
                --  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);
@@ -1252,6 +1268,8 @@ package body System.Task_Primitives.Operations is
       --    's'   Interrupt_State pragma set state to System (use "default"
       --           system handler)
 
+      use type System.Multiprocessors.CPU_Range;
+
    begin
       Environment_Task_Id := Environment_Task;
 
@@ -1312,6 +1330,25 @@ package body System.Task_Primitives.Operations is
          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;