+2011-09-01 Jose Ruiz <ruiz@adacore.com>
+
+ * adaint.c, adaint.h (__gnat_cpu_alloc, __gnat_cpu_alloc_size,
+ __gnat_cpu_set_free): Create these wrappers around the CPU_ALLOC,
+ CPU_ALLOC_SIZE and CPU_FREE linux macros.
+ (__gnat_cpu_zero, __gnat_cpu_set): Use the CPU_ZERO_S and
+ CPU_SET_S respectively because we are now using dynamically allocated
+ CPU sets which are more portable across different glibc versions.
+ * s-osinte-linux.ads (cpu_set_t_ptr, CPU_ALLOC, CPU_ALLOC_SIZE,
+ CPU_FREE): Add this type and subprograms to be able to create cpu_set_t
+ masks dynamically according to the number of processors in the target
+ platform.
+ (CPU_ZERO, CPU_SET): They are now mapped to the CPU_ZERO_S and CPU_SET_S
+ respectively, so we need to pass the size of the masks as
+ parameters.
+ * s-taprop-linux.adb (Create_Task, Set_Task_Affinity): Use dynamically
+ created cpu_set_t masks
+ with the number of processors available in the target platform,
+ instead of static bit arrays. It enhances portability because
+ it uses the information from the target platform.
+ * sem_ch8.adb: (Attribute_Renaming): When checking whether we
+ are using a restricted run-time library, use the flag
+ Configurable_Run_Time_Mode instead of Restricted_Profile.
+
2011-09-01 Vincent Celier <celier@adacore.com>
* ug_words: Add /MULTI_UNIT_INDEX= -> -gnateI
#include <sched.h>
-void __gnat_cpu_zero (cpu_set_t *set)
+cpu_set_t *__gnat_cpu_alloc (size_t count)
{
- CPU_ZERO (set);
+ return CPU_ALLOC (count);
}
-void __gnat_cpu_set (int cpu, cpu_set_t *set)
+size_t __gnat_cpu_alloc_size (size_t count)
+{
+ return CPU_ALLOC_SIZE (count);
+}
+
+void __gnat_cpu_free (cpu_set_t *set)
+{
+ CPU_FREE (set);
+}
+
+void __gnat_cpu_zero (size_t count, cpu_set_t *set)
+{
+ CPU_ZERO_S (count, set);
+}
+
+void __gnat_cpu_set (int cpu, size_t count, cpu_set_t *set)
{
/* Ada handles CPU numbers starting from 1, while C identifies the first
CPU by a 0, so we need to adjust. */
- CPU_SET (cpu - 1, set);
+ CPU_SET_S (cpu - 1, count, set);
}
#endif
#include <sched.h>
-extern void __gnat_cpu_zero (cpu_set_t *);
-extern void __gnat_cpu_set (int, cpu_set_t *);
+extern cpu_set_t *__gnat_cpu_alloc (size_t);
+extern size_t __gnat_cpu_alloc_size (size_t);
+extern void __gnat_cpu_set_free (cpu_set_t *);
+extern void __gnat_cpu_zero (size_t, cpu_set_t *);
+extern void __gnat_cpu_set (int, size_t, cpu_set_t *);
#endif
#if defined (_WIN32)
pragma Import (C, pthread_key_create, "pthread_key_create");
CPU_SETSIZE : constant := 1_024;
+ -- Size of the cpu_set_t mask on most linux systems (SUSE 11 uses 4_096).
+ -- This is kept for backward compatibility (System.Task_Info uses it), but
+ -- the run-time library does no longer rely on static masks, using
+ -- dynamically allocated masks instead.
type bit_field is array (1 .. CPU_SETSIZE) of Boolean;
for bit_field'Size use CPU_SETSIZE;
end record;
pragma Convention (C, cpu_set_t);
- procedure CPU_ZERO (cpuset : access cpu_set_t);
+ type cpu_set_t_ptr is access all cpu_set_t;
+ -- In the run-time library we use this pointer because the size of type
+ -- cpu_set_t varies depending on the glibc version. Hence, objects of type
+ -- cpu_set_t are allocated dynamically using the number of processors
+ -- available in the target machine (value obtained at execution time).
+
+ function CPU_ALLOC (count : size_t) return cpu_set_t_ptr;
+ pragma Import (C, CPU_ALLOC, "__gnat_cpu_alloc");
+ -- Wrapper around the CPU_ALLOC C macro
+
+ function CPU_ALLOC_SIZE (count : size_t) return size_t;
+ pragma Import (C, CPU_ALLOC_SIZE, "__gnat_cpu_alloc_size");
+ -- Wrapper around the CPU_ALLOC_SIZE C macro
+
+ procedure CPU_FREE (cpuset : cpu_set_t_ptr);
+ pragma Import (C, CPU_FREE, "__gnat_cpu_free");
+ -- Wrapper around the CPU_FREE C macro
+
+ procedure CPU_ZERO (count : size_t; cpuset : cpu_set_t_ptr);
pragma Import (C, CPU_ZERO, "__gnat_cpu_zero");
- -- Wrapper around the CPU_ZERO C macro
+ -- Wrapper around the CPU_ZERO_S C macro
- procedure CPU_SET (cpu : int; cpuset : access cpu_set_t);
+ procedure CPU_SET (cpu : int; count : size_t; cpuset : cpu_set_t_ptr);
pragma Import (C, CPU_SET, "__gnat_cpu_set");
- -- Wrapper around the CPU_SET C macro
+ -- Wrapper around the CPU_SET_S C macro
function pthread_setaffinity_np
(thread : pthread_t;
cpusetsize : size_t;
- cpuset : access cpu_set_t) return int;
+ cpuset : cpu_set_t_ptr) return int;
pragma Import (C, pthread_setaffinity_np, "pthread_setaffinity_np");
pragma Weak_External (pthread_setaffinity_np);
-- Use a weak symbol because this function may be available or not,
function pthread_attr_setaffinity_np
(attr : access pthread_attr_t;
cpusetsize : size_t;
- cpuset : access cpu_set_t) return int;
+ cpuset : cpu_set_t_ptr) return int;
pragma Import (C, pthread_attr_setaffinity_np,
"pthread_attr_setaffinity_np");
pragma Weak_External (pthread_attr_setaffinity_np);
elsif T.Common.Base_CPU /= System.Multiprocessors.Not_A_Specific_CPU then
declare
- CPU_Set : aliased cpu_set_t;
+ CPUs : constant size_t :=
+ Interfaces.C.size_t (System.Multiprocessors.Number_Of_CPUs);
+ CPU_Set : constant cpu_set_t_ptr := CPU_ALLOC (CPUs);
+ Size : constant size_t := CPU_ALLOC_SIZE (CPUs);
begin
- System.OS_Interface.CPU_ZERO (CPU_Set'Access);
+ CPU_ZERO (Size, CPU_Set);
System.OS_Interface.CPU_SET
- (int (T.Common.Base_CPU), CPU_Set'Access);
+ (int (T.Common.Base_CPU), Size, CPU_Set);
Result :=
- pthread_attr_setaffinity_np
- (Attributes'Access,
- CPU_SETSIZE / 8,
- CPU_Set'Access);
+ pthread_attr_setaffinity_np (Attributes'Access, Size, CPU_Set);
pragma Assert (Result = 0);
+
+ CPU_FREE (CPU_Set);
end;
-- Handle Task_Info
- elsif T.Common.Task_Info /= null
- and then T.Common.Task_Info.CPU_Affinity /= Task_Info.Any_CPU
- then
+ elsif T.Common.Task_Info /= null then
Result :=
pthread_attr_setaffinity_np
(Attributes'Access,
Multiprocessors.Number_Of_CPUs => True))
then
declare
- CPU_Set : aliased cpu_set_t;
+ CPUs : constant size_t :=
+ Interfaces.C.size_t (System.Multiprocessors.Number_Of_CPUs);
+ CPU_Set : constant cpu_set_t_ptr := CPU_ALLOC (CPUs);
+ Size : constant size_t := CPU_ALLOC_SIZE (CPUs);
begin
- System.OS_Interface.CPU_ZERO (CPU_Set'Access);
+ CPU_ZERO (Size, CPU_Set);
-- Set the affinity to all the processors belonging to the
-- dispatching domain.
for Proc in T.Common.Domain'Range loop
if T.Common.Domain (Proc) then
- System.OS_Interface.CPU_SET (int (Proc), CPU_Set'Access);
+ System.OS_Interface.CPU_SET (int (Proc), Size, CPU_Set);
end if;
end loop;
Result :=
- pthread_attr_setaffinity_np
- (Attributes'Access,
- CPU_SETSIZE / 8,
- CPU_Set'Access);
+ pthread_attr_setaffinity_np (Attributes'Access, Size, CPU_Set);
pragma Assert (Result = 0);
+
+ CPU_FREE (CPU_Set);
end;
end if;
and then T.Common.LL.Thread /= Null_Thread_Id
then
declare
- type cpu_set_t_ptr is access all cpu_set_t;
- CPU_Set : aliased cpu_set_t;
- CPU_Set_Ptr : cpu_set_t_ptr := null;
+ CPUs : constant size_t :=
+ Interfaces.C.size_t (System.Multiprocessors.Number_Of_CPUs);
+ CPU_Set : cpu_set_t_ptr := null;
+ Size : constant size_t := CPU_ALLOC_SIZE (CPUs);
Result : Interfaces.C.int;
if T.Common.Base_CPU /= Multiprocessors.Not_A_Specific_CPU then
-- Set the affinity to an unique CPU
- System.OS_Interface.CPU_ZERO (CPU_Set'Access);
+
+ CPU_Set := CPU_ALLOC (CPUs);
+ System.OS_Interface.CPU_ZERO (Size, CPU_Set);
System.OS_Interface.CPU_SET
- (int (T.Common.Base_CPU), CPU_Set'Access);
- CPU_Set_Ptr := CPU_Set'Access;
+ (int (T.Common.Base_CPU), Size, CPU_Set);
-- Handle Task_Info
- elsif T.Common.Task_Info /= null
- and then T.Common.Task_Info.CPU_Affinity /= Task_Info.Any_CPU
- then
- CPU_Set_Ptr := T.Common.Task_Info.CPU_Affinity'Access;
+ elsif T.Common.Task_Info /= null then
+ CPU_Set := T.Common.Task_Info.CPU_Affinity'Access;
-- Handle dispatching domains
-- domain other than the default one, or when the default one
-- has been modified.
- System.OS_Interface.CPU_ZERO (CPU_Set'Access);
+ CPU_Set := CPU_ALLOC (CPUs);
+ System.OS_Interface.CPU_ZERO (Size, CPU_Set);
for Proc in T.Common.Domain'Range loop
- System.OS_Interface.CPU_SET (int (Proc), CPU_Set'Access);
+ System.OS_Interface.CPU_SET (int (Proc), Size, CPU_Set);
end loop;
-
- CPU_Set_Ptr := CPU_Set'Access;
end if;
-- We set the new affinity if needed. Otherwise, the new task
-- the documentation of pthread_setaffinity_np), which is
-- consistent with Ada's required semantics.
- if CPU_Set_Ptr /= null then
+ if CPU_Set /= null then
Result :=
- pthread_setaffinity_np
- (T.Common.LL.Thread, CPU_SETSIZE / 8, CPU_Set_Ptr);
+ pthread_setaffinity_np (T.Common.LL.Thread, Size, CPU_Set);
pragma Assert (Result = 0);
+
+ CPU_FREE (CPU_Set);
end if;
end;
end if;
-- We must exclude VM targets and restricted run-time libraries because
-- entity AST_Handler is defined in package System.Aux_Dec which is not
- -- available in those platforms.
+ -- available in those platforms. Note that we cannot use the function
+ -- Restricted_Profile (instead of Configurable_Run_Time_Mode) because
+ -- the ZFP run-time library is not defined as a profile, and we do not
+ -- want to deal with AST_Handler in ZFP mode.
if VM_Target = No_VM
- and then not Restricted_Profile
+ and then not Configurable_Run_Time_Mode
and then not Present (Corresponding_Formal_Spec (N))
and then Etype (Nam) /= RTE (RE_AST_Handler)
then