OSDN Git Service

2007-12-06 Pascal Obry <obry@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Dec 2007 10:18:44 +0000 (10:18 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Dec 2007 10:18:44 +0000 (10:18 +0000)
* adaint.c (__gnat_pthread_setaffinity_np): New routine. A dummy
 version is provided for older GNU/Linux distribution not
 supporting thread affinity sets.

* s-osinte-linux.ads (SC_NPROCESSORS_ONLN): New constant for sysconf
call.
(bit_field): New packed boolean type used by cpu_set_t.
(cpu_set_t): New type corresponding to the C type with
the same name. Note that on the Ada side we use a bit
field array for the affinity mask. There is not need
for the C macro for setting individual bit.
(pthread_setaffinity_np): New imported routine.

* s-taprop-linux.adb (Enter_Task): Check that the CPU affinity mask is
no null.
(Create_Task): Set the processor affinity mask if information
is present.

* s-tasinf-linux.ads, s-tasinf-linux.adb: New files.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@130812 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/adaint.c
gcc/ada/s-osinte-linux.ads
gcc/ada/s-taprop-linux.adb
gcc/ada/s-tasinf-linux.adb [new file with mode: 0644]
gcc/ada/s-tasinf-linux.ads [new file with mode: 0644]

index 366a476..6c5d440 100644 (file)
 #include "version.h"
 #endif
 
-#if defined (__MINGW32__)
+#if defined (RTX)
+#include <windows.h>
+#include <Rtapi.h>
+#include <sys/utime.h>
+
+#elif defined (__MINGW32__)
 
 #include "mingw32.h"
 #include <sys/utime.h>
@@ -995,7 +1000,12 @@ __gnat_tmp_name (char *tmp_filename)
 
 DIR* __gnat_opendir (char *name)
 {
-#ifdef __MINGW32__
+#if defined (RTX)
+  /* Not supported in RTX */
+
+  return NULL;
+
+#elif defined (__MINGW32__)
   TCHAR wname[GNAT_MAX_PATH_LEN];
 
   S2WSU (wname, name, GNAT_MAX_PATH_LEN);
@@ -1012,7 +1022,11 @@ DIR* __gnat_opendir (char *name)
 char *
 __gnat_readdir (DIR *dirp, char *buffer, int *len)
 {
-#if defined (__MINGW32__)
+#if defined (RTX)
+  /* Not supported in RTX */
+
+  return NULL;
+#elif defined (__MINGW32__)
   struct _tdirent *dirent = _treaddir ((_TDIR*)dirp);
 
   if (dirent != NULL)
@@ -1054,7 +1068,12 @@ __gnat_readdir (DIR *dirp, char *buffer, int *len)
 
 int __gnat_closedir (DIR *dirp)
 {
-#ifdef __MINGW32__
+#if defined (RTX)
+  /* Not supported in RTX */
+
+  return 0;
+
+#elif defined (__MINGW32__)
   return _tclosedir ((_TDIR*)dirp);
 
 #else
@@ -1074,7 +1093,7 @@ __gnat_readdir_is_thread_safe (void)
 #endif
 }
 
-#ifdef _WIN32
+#if defined (_WIN32) && !defined (RTX)
 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>.  */
 static const unsigned long long w32_epoch_offset = 11644473600ULL;
 
@@ -1114,7 +1133,7 @@ __gnat_file_time_name (char *name)
   close (fd);
   return (OS_Time)ret;
 
-#elif defined (_WIN32)
+#elif defined (_WIN32) && !defined (RTX)
   time_t ret = -1;
   TCHAR wname[GNAT_MAX_PATH_LEN];
 
@@ -1217,7 +1236,7 @@ __gnat_file_time_fd (int fd)
   tot_secs += file_tsec * 2;
   return (OS_Time) tot_secs;
 
-#elif defined (_WIN32)
+#elif defined (_WIN32) && !defined (RTX)
   HANDLE h = (HANDLE) _get_osfhandle (fd);
   time_t ret = win32_filetime (h);
   return (OS_Time) ret;
@@ -1247,7 +1266,7 @@ __gnat_set_file_time_name (char *name, time_t time_stamp)
 
 /* Code to implement __gnat_set_file_time_name for these systems.  */
 
-#elif defined (_WIN32)
+#elif defined (_WIN32) && !defined (RTX)
   union
   {
     FILETIME ft_time;
@@ -1462,7 +1481,7 @@ __gnat_get_libraries_from_registry (void)
 {
   char *result = (char *) "";
 
-#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
+#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE) && ! defined (RTX)
 
   HKEY reg_key;
   DWORD name_size, value_size;
@@ -1552,7 +1571,7 @@ __gnat_stat (char *name, struct stat *statbuf)
 int
 __gnat_file_exists (char *name)
 {
-#ifdef __MINGW32__
+#if defined (__MINGW32__) && !defined (RTX)
   /*  On Windows do not use __gnat_stat() because a bug in Microsoft
   _stat() routine. When the system time-zone is set with a negative
   offset the _stat() routine fails on specific files like CON:  */
@@ -1720,7 +1739,10 @@ __gnat_portable_spawn (char *args[])
   int finished ATTRIBUTE_UNUSED;
   int pid ATTRIBUTE_UNUSED;
 
-#if defined (MSDOS) || defined (_WIN32)
+#if defined (__vxworks) || defined(__nucleus__) || defined(RTX)
+  return -1;
+
+#elif defined (MSDOS) || defined (_WIN32)
   /* args[0] must be quotes as it could contain a full pathname with spaces */
   char *args_0 = args[0];
   args[0] = (char *)xmalloc (strlen (args_0) + 3);
@@ -1739,8 +1761,6 @@ __gnat_portable_spawn (char *args[])
   else
     return status;
 
-#elif defined (__vxworks) || defined(__nucleus__)
-  return -1;
 #else
 
 #ifdef __EMX__
@@ -1809,7 +1829,7 @@ __gnat_dup2 (int oldfd, int newfd)
 
 /* WIN32 code to implement a wait call that wait for any child process.  */
 
-#ifdef _WIN32
+#if defined (_WIN32) && !defined (RTX)
 
 /* Synchronization code, to be thread safe.  */
 
@@ -2021,7 +2041,10 @@ __gnat_portable_no_block_spawn (char *args[])
 {
   int pid = 0;
 
-#if defined (__EMX__) || defined (MSDOS)
+#if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
+  return -1;
+
+#elif defined (__EMX__) || defined (MSDOS)
 
   /* ??? For PC machines I (Franco) don't know the system calls to implement
      this routine. So I'll fake it as follows. This routine will behave
@@ -2039,9 +2062,6 @@ __gnat_portable_no_block_spawn (char *args[])
   pid = win32_no_block_spawn (args[0], args);
   return pid;
 
-#elif defined (__vxworks) || defined (__nucleus__)
-  return -1;
-
 #else
   pid = fork ();
 
@@ -2067,16 +2087,17 @@ __gnat_portable_wait (int *process_status)
   int status = 0;
   int pid = 0;
 
-#if defined (_WIN32)
+#if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
+  /* Not sure what to do here, so do same as __EMX__ case, i.e., nothing but
+     return zero.  */
+
+#elif defined (_WIN32)
 
   pid = win32_wait (&status);
 
 #elif defined (__EMX__) || defined (MSDOS)
   /* ??? See corresponding comment in portable_no_block_spawn.  */
 
-#elif defined (__vxworks) || defined (__nucleus__)
-  /* Not sure what to do here, so do same as __EMX__ case, i.e., nothing but
-     return zero.  */
 #else
 
   pid = waitpid (-1, &status, 0);
@@ -2218,7 +2239,7 @@ __gnat_locate_exec_on_path (char *exec_name)
 {
   char *apath_val;
 
-#ifdef _WIN32
+#if defined (_WIN32) && !defined (RTX)
   TCHAR *wpath_val = _tgetenv (_T("PATH"));
   TCHAR *wapath_val;
   /* In Win32 systems we expand the PATH as for XP environment
@@ -2990,3 +3011,42 @@ __gnat_sals_init_using_constructors ()
    return 1;
 #endif
 }
+
+/* In RTX mode, the procedure to get the time (as file time) is different
+   in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
+   we introduce an intermediate procedure to link against the corresponding
+   one in each situation. */
+#ifdef RTX
+
+void GetTimeAsFileTime(LPFILETIME pTime)
+{
+#ifdef RTSS
+  RtGetRtssTimeAsFileTime (pTime); /* RTSS interface */
+#else
+  GetSystemTimeAsFileTime (pTime); /* w32 interface */
+#endif
+}
+#endif
+
+#if defined (linux)
+/* pthread affinity support */
+
+#ifdef CPU_SETSIZE
+#include <pthread.h>
+int
+__gnat_pthread_setaffinity_np (pthread_t th,
+                              size_t cpusetsize,
+                              const cpu_set_t *cpuset)
+{
+  return pthread_setaffinity_np (th, cpusetsize, cpuset);
+}
+#else
+int
+__gnat_pthread_setaffinity_np (pthread_t th,
+                              size_t cpusetsize,
+                              const void *cpuset)
+{
+  return 0;
+}
+#endif
+#endif
index 751e3b8..7299123 100644 (file)
@@ -241,7 +241,8 @@ package System.OS_Interface is
    function sysconf (name : int) return long;
    pragma Import (C, sysconf);
 
-   SC_CLK_TCK : constant := 2;
+   SC_CLK_TCK          : constant := 2;
+   SC_NPROCESSORS_ONLN : constant := 84;
 
    -------------------------
    -- Priority Scheduling --
@@ -253,7 +254,7 @@ package System.OS_Interface is
 
    function To_Target_Priority
      (Prio : System.Any_Priority) return Interfaces.C.int;
-   --  Maps System.Any_Priority to a POSIX priority.
+   --  Maps System.Any_Priority to a POSIX priority
 
    -------------
    -- Process --
@@ -273,6 +274,7 @@ package System.OS_Interface is
 
    type Thread_Body is access
      function (arg : System.Address) return System.Address;
+   pragma Convention (C, Thread_Body);
 
    function Thread_Body_Access is new
      Ada.Unchecked_Conversion (System.Address, Thread_Body);
@@ -453,12 +455,31 @@ package System.OS_Interface is
    pragma Import (C, pthread_getspecific, "pthread_getspecific");
 
    type destructor_pointer is access procedure (arg : System.Address);
+   pragma Convention (C, destructor_pointer);
 
    function pthread_key_create
      (key        : access pthread_key_t;
       destructor : destructor_pointer) return int;
    pragma Import (C, pthread_key_create, "pthread_key_create");
 
+   CPU_SETSIZE : constant := 1_024;
+
+   type bit_field is array (1 .. CPU_SETSIZE) of Boolean;
+   for bit_field'Size use CPU_SETSIZE;
+   pragma Pack (bit_field);
+   pragma Convention (C, bit_field);
+
+   type cpu_set_t is record
+      bits : bit_field;
+   end record;
+   pragma Convention (C, cpu_set_t);
+
+   function pthread_setaffinity_np
+     (thread     : pthread_t;
+      cpusetsize : size_t;
+      cpuset     : access cpu_set_t) return int;
+   pragma Import (C, pthread_setaffinity_np, "__gnat_pthread_setaffinity_np");
+
 private
 
    type sigset_t is array (0 .. 127) of unsigned_char;
index 8e0f241..21e2a65 100644 (file)
@@ -44,6 +44,9 @@ with Interfaces.C;
 --  used for int
 --           size_t
 
+with System.Task_Info;
+--  used for Unspecified_Task_Info
+
 with System.Tasking.Debug;
 --  used for Known_Tasks
 
@@ -87,6 +90,7 @@ package body System.Task_Primitives.Operations is
    use System.Parameters;
    use System.OS_Primitives;
    use System.Storage_Elements;
+   use System.Task_Info;
 
    ----------------
    -- Local Data --
@@ -764,6 +768,13 @@ package body System.Task_Primitives.Operations is
 
    procedure Enter_Task (Self_ID : Task_Id) is
    begin
+      if Self_ID.Common.Task_Info /= null
+        and then
+          Self_ID.Common.Task_Info.CPU_Affinity = No_CPU
+      then
+         raise Invalid_CPU_Number;
+      end if;
+
       Self_ID.Common.LL.Thread := pthread_self;
 
       Specific.Set (Self_ID);
@@ -911,6 +922,19 @@ package body System.Task_Primitives.Operations is
 
       Succeeded := Result = 0;
 
+      --  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);
 
diff --git a/gcc/ada/s-tasinf-linux.adb b/gcc/ada/s-tasinf-linux.adb
new file mode 100644 (file)
index 0000000..0510a63
--- /dev/null
@@ -0,0 +1,57 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                     S Y S T E M . T A S K _ I N F O                      --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--            Copyright (C) 2007, Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This is the GNU/Linux version of this module
+
+package body System.Task_Info is
+
+   N_CPU : Natural := 0;
+   pragma Atomic (N_CPU);
+   --  Cache CPU number. Use pragma Atomic to avoid a race condition when
+   --  setting N_CPU in Number_Of_Processors below.
+
+   --------------------------
+   -- Number_Of_Processors --
+   --------------------------
+
+   function Number_Of_Processors return Positive is
+   begin
+      if N_CPU = 0 then
+         N_CPU := Natural
+           (OS_Interface.sysconf (OS_Interface.SC_NPROCESSORS_ONLN));
+      end if;
+
+      return N_CPU;
+   end Number_Of_Processors;
+
+end System.Task_Info;
diff --git a/gcc/ada/s-tasinf-linux.ads b/gcc/ada/s-tasinf-linux.ads
new file mode 100644 (file)
index 0000000..603a118
--- /dev/null
@@ -0,0 +1,103 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                     S Y S T E M . T A S K _ I N F O                      --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--            Copyright (C) 2007, Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT 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- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the definitions and routines associated with the
+--  implementation and use of the Task_Info pragma. It is specialized
+--  appropriately for targets that make use of this pragma.
+
+--  Note: the compiler generates direct calls to this interface, via Rtsfind.
+--  Any changes to this interface may require corresponding compiler changes.
+
+--  This unit may be used directly from an application program by providing
+--  an appropriate WITH, and the interface can be expected to remain stable.
+
+--  This is the GNU/Linux version of this module.
+
+with System.OS_Interface;
+
+package System.Task_Info is
+   pragma Preelaborate;
+   pragma Elaborate_Body;
+   --  To ensure that a body is allowed
+
+   --  Windows provides a way to define the ideal processor to use for a given
+   --  thread. The ideal processor is not necessarily the one that will be used
+   --  by the OS but the OS will always try to schedule this thread to the
+   --  specified processor if it is available.
+
+   --  The Task_Info pragma:
+
+   --    pragma Task_Info (EXPRESSION);
+
+   --  allows the specification on a task by task basis of a value of type
+   --  System.Task_Info.Task_Info_Type to be passed to a task when it is
+   --  created. The specification of this type, and the effect on the task
+   --  that is created is target dependent.
+
+   --  The Task_Info pragma appears within a task definition (compare the
+   --  definition and implementation of pragma Priority). If no such pragma
+   --  appears, then the value Unspecified_Task_Info is passed. If a pragma
+   --  is present, then it supplies an alternative value. If the argument of
+   --  the pragma is a discriminant reference, then the value can be set on
+   --  a task by task basis by supplying the appropriate discriminant value.
+
+   --  Note that this means that the type used for Task_Info_Type must be
+   --  suitable for use as a discriminant (i.e. a scalar or access type).
+
+   -----------------------
+   -- Thread Attributes --
+   -----------------------
+
+   subtype CPU_Set is System.OS_Interface.cpu_set_t;
+
+   Any_CPU : constant CPU_Set := (bits => (others => True));
+   No_CPU  : constant CPU_Set := (bits => (others => False));
+
+   Invalid_CPU_Number : exception;
+   --  Raised when an invalid CPU mask has been specified
+   --  i.e. An empty CPU set
+
+   type Thread_Attributes is record
+      CPU_Affinity : aliased CPU_Set := Any_CPU;
+   end record;
+
+   Default_Thread_Attributes : constant Thread_Attributes := (others => <>);
+
+   type Task_Info_Type is access all Thread_Attributes;
+
+   Unspecified_Task_Info : constant Task_Info_Type := null;
+
+   function Number_Of_Processors return Positive;
+   --  Returns the number of processors on the running host
+
+end System.Task_Info;