diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-12-13 10:18:44 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-12-13 10:18:44 +0000 |
commit | e2a33c1825a7cbbb0061b24d7fccf70c172ddd5e (patch) | |
tree | aab7a215c62fc85b658d90381374889f961afcaa /gcc/ada | |
parent | 85b21747512bbed0231baff8af70125cdd9c5899 (diff) | |
download | gcc-e2a33c1825a7cbbb0061b24d7fccf70c172ddd5e.tar.gz |
2007-12-06 Pascal Obry <obry@adacore.com>
* 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
Diffstat (limited to 'gcc/ada')
-rw-r--r-- | gcc/ada/adaint.c | 106 | ||||
-rw-r--r-- | gcc/ada/s-osinte-linux.ads | 25 | ||||
-rw-r--r-- | gcc/ada/s-taprop-linux.adb | 24 | ||||
-rw-r--r-- | gcc/ada/s-tasinf-linux.adb | 57 | ||||
-rw-r--r-- | gcc/ada/s-tasinf-linux.ads | 103 |
5 files changed, 290 insertions, 25 deletions
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index 366a476c8e4..6c5d440a568 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c @@ -76,7 +76,12 @@ #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 diff --git a/gcc/ada/s-osinte-linux.ads b/gcc/ada/s-osinte-linux.ads index 751e3b8238a..7299123deb7 100644 --- a/gcc/ada/s-osinte-linux.ads +++ b/gcc/ada/s-osinte-linux.ads @@ -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; diff --git a/gcc/ada/s-taprop-linux.adb b/gcc/ada/s-taprop-linux.adb index 8e0f241cc07..21e2a6589c6 100644 --- a/gcc/ada/s-taprop-linux.adb +++ b/gcc/ada/s-taprop-linux.adb @@ -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 index 00000000000..0510a630824 --- /dev/null +++ b/gcc/ada/s-tasinf-linux.adb @@ -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 index 00000000000..603a1189b6b --- /dev/null +++ b/gcc/ada/s-tasinf-linux.ads @@ -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; |