Patchwork [Ada] Use the CPU_ZERO and CPU_SET linux macros

login
register
mail settings
Submitter Arnaud Charlet
Date Sept. 1, 2011, 1:32 p.m.
Message ID <20110901133213.GA3122@adacore.com>
Download mbox | patch
Permalink /patch/112911/
State New
Headers show

Comments

Arnaud Charlet - Sept. 1, 2011, 1:32 p.m.
CPU sets are properly handled in linux using the macros defined for this
effect. This way we avoid problems with the endianness of the target if we
try to modify the bit set by hand.

No functional change.

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-09-01  Jose Ruiz  <ruiz@adacore.com>

	* s-taprop-linux.adb (Create_Task, Set_Task_Affinity): Use the linux
	macros for handling CPU sets (CPU_ZERO, CPU_SET) instead of modifying
	directly the bit array.
	* s-osinte-linux.ads (CPU_ZERO, CPU_SET): Import these wrappers around
	the linux macros with the same name.
	* adaint.h, adaint.c (__gnat_cpu_zero, __gnat_cpu_set): Create these
	wrappers around the CPU_ZERO and CPU_SET linux macros.

Patch

Index: s-osinte-linux.ads
===================================================================
--- s-osinte-linux.ads	(revision 178381)
+++ s-osinte-linux.ads	(working copy)
@@ -7,7 +7,7 @@ 
 --                                  S p e c                                 --
 --                                                                          --
 --             Copyright (C) 1991-1994, Florida State University            --
---          Copyright (C) 1995-2010, Free Software Foundation, Inc.         --
+--          Copyright (C) 1995-2011, 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- --
@@ -482,6 +482,14 @@ 
    end record;
    pragma Convention (C, cpu_set_t);
 
+   procedure CPU_ZERO (cpuset : access cpu_set_t);
+   pragma Import (C, CPU_ZERO, "__gnat_cpu_zero");
+   --  Wrapper around the CPU_ZERO C macro
+
+   procedure CPU_SET (cpu : int; cpuset : access cpu_set_t);
+   pragma Import (C, CPU_SET, "__gnat_cpu_set");
+   --  Wrapper around the CPU_SET C macro
+
    function pthread_setaffinity_np
      (thread     : pthread_t;
       cpusetsize : size_t;
Index: s-taprop-linux.adb
===================================================================
--- s-taprop-linux.adb	(revision 178398)
+++ s-taprop-linux.adb	(working copy)
@@ -869,9 +869,12 @@ 
 
       elsif T.Common.Base_CPU /= System.Multiprocessors.Not_A_Specific_CPU then
          declare
-            CPU_Set : aliased cpu_set_t := (bits => (others => False));
+            CPU_Set : aliased cpu_set_t;
+
          begin
-            CPU_Set.bits (Integer (T.Common.Base_CPU)) := True;
+            System.OS_Interface.CPU_ZERO (CPU_Set'Access);
+            System.OS_Interface.CPU_SET
+              (int (T.Common.Base_CPU), CPU_Set'Access);
             Result :=
               pthread_attr_setaffinity_np
                 (Attributes'Access,
@@ -905,14 +908,18 @@ 
                      Multiprocessors.Number_Of_CPUs => True))
       then
          declare
-            CPU_Set : aliased cpu_set_t := (bits => (others => False));
+            CPU_Set : aliased cpu_set_t;
 
          begin
+            System.OS_Interface.CPU_ZERO (CPU_Set'Access);
+
             --  Set the affinity to all the processors belonging to the
             --  dispatching domain.
 
             for Proc in T.Common.Domain'Range loop
-               CPU_Set.bits (Integer (Proc)) := T.Common.Domain (Proc);
+               if T.Common.Domain (Proc) then
+                  System.OS_Interface.CPU_SET (int (Proc), CPU_Set'Access);
+               end if;
             end loop;
 
             Result :=
@@ -1394,8 +1401,9 @@ 
       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;
 
-            CPU_Set : cpu_set_t_ptr := null;
             Result  : Interfaces.C.int;
 
          begin
@@ -1406,16 +1414,17 @@ 
             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);
+               System.OS_Interface.CPU_SET
+                 (int (T.Common.Base_CPU), CPU_Set'Access);
+               CPU_Set_Ptr := CPU_Set'Access;
 
-               CPU_Set := new cpu_set_t'(bits => (others => False));
-               CPU_Set.bits (Integer (T.Common.Base_CPU)) := True;
-
             --  Handle Task_Info
 
             elsif T.Common.Task_Info /= null
               and then T.Common.Task_Info.CPU_Affinity /= Task_Info.Any_CPU
             then
-               CPU_Set := T.Common.Task_Info.CPU_Affinity'Access;
+               CPU_Set_Ptr := T.Common.Task_Info.CPU_Affinity'Access;
 
             --  Handle dispatching domains
 
@@ -1431,11 +1440,13 @@ 
                --  domain other than the default one, or when the default one
                --  has been modified.
 
-               CPU_Set := new cpu_set_t'(bits => (others => False));
+               System.OS_Interface.CPU_ZERO (CPU_Set'Access);
 
                for Proc in T.Common.Domain'Range loop
-                  CPU_Set.bits (Integer (Proc)) := T.Common.Domain (Proc);
+                  System.OS_Interface.CPU_SET (int (Proc), CPU_Set'Access);
                end loop;
+
+               CPU_Set_Ptr := CPU_Set'Access;
             end if;
 
             --  We set the new affinity if needed. Otherwise, the new task
@@ -1443,10 +1454,10 @@ 
             --  the documentation of pthread_setaffinity_np), which is
             --  consistent with Ada's required semantics.
 
-            if CPU_Set /= null then
+            if CPU_Set_Ptr /= null then
                Result :=
                  pthread_setaffinity_np
-                   (T.Common.LL.Thread, CPU_SETSIZE / 8, CPU_Set);
+                   (T.Common.LL.Thread, CPU_SETSIZE / 8, CPU_Set_Ptr);
                pragma Assert (Result = 0);
             end if;
          end;
Index: adaint.c
===================================================================
--- adaint.c	(revision 178381)
+++ adaint.c	(working copy)
@@ -3770,6 +3770,20 @@ 
 {
    return (void *) syscall (__NR_gettid);
 }
+
+#include <sched.h>
+
+void __gnat_cpu_zero (cpu_set_t *set)
+{
+  CPU_ZERO (set);
+}
+
+void __gnat_cpu_set (int cpu, 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);
+}
 #endif
 
 #ifdef __cplusplus
Index: adaint.h
===================================================================
--- adaint.h	(revision 178381)
+++ adaint.h	(working copy)
@@ -247,6 +247,13 @@ 
 						    int *, char *, int *);
 #if defined (linux)
 extern void   *__gnat_lwp_self			   (void);
+
+/* Routines for interface to required CPU set primitives */
+
+#include <sched.h>
+
+extern void   __gnat_cpu_zero                      (cpu_set_t *);
+extern void   __gnat_cpu_set                       (int, cpu_set_t *);
 #endif
 
 #if defined (_WIN32)