summaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2007-12-13 10:18:44 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2007-12-13 10:18:44 +0000
commite2a33c1825a7cbbb0061b24d7fccf70c172ddd5e (patch)
treeaab7a215c62fc85b658d90381374889f961afcaa /gcc/ada
parent85b21747512bbed0231baff8af70125cdd9c5899 (diff)
downloadgcc-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.c106
-rw-r--r--gcc/ada/s-osinte-linux.ads25
-rw-r--r--gcc/ada/s-taprop-linux.adb24
-rw-r--r--gcc/ada/s-tasinf-linux.adb57
-rw-r--r--gcc/ada/s-tasinf-linux.ads103
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;