Example #1
0
/****** shepherd_binding/bind_process_to_mask() *************************************
*  NAME
*     bind_process_to_mask() -- Binds a process to a given cpuset (mask). 
*
*  SYNOPSIS
*     static bool bind_process_to_mask(const pid_t pid, const plpa_cpu_set_t 
*     cpuset) 
*
*  FUNCTION
*     Binds a process to a given cpuset. 
*
*  INPUTS
*     const pid_t pid             - Process to bind 
*     const plpa_cpu_set_t cpuset - Processors to bind processes to 
*
*  RESULT
*     static bool - true if successful, false otherwise
*
*  NOTES
*     MT-NOTE: bind_process_to_mask() is not MT safe 
*
*******************************************************************************/
static bool bind_process_to_mask(const pid_t pid, const plpa_cpu_set_t cpuset)
{
   if (has_core_binding()) {
      /* we only need core binding capabilites, no topology is required */
      
      /* DG TODO delete addres and change header in order to make cputset to pointer */ 
      if (plpa_sched_setaffinity(pid, sizeof(plpa_cpu_set_t), &cpuset) != 0) {
         return false;
      } else {
         return true;
      }
   }
   
   return false;
}
Example #2
0
/****** sge_binding_hlp/get_amount_of_plpa_sockets() ************************************
*  NAME
*     get_amount_of_plpa_sockets() -- Get the amount of available sockets.  
*
*  SYNOPSIS
*     int get_amount_of_plpa_sockets() 
*
*  FUNCTION
*     Returns the amount of sockets available on this system. 
*
*  RESULT
*     int - The amount of available sockets on system. 0 in case of 
*                  of an error.
*
*  NOTES
*     MT-NOTE: get_amount_of_plpa_sockets() is not MT safe 
*
*******************************************************************************/
int get_amount_of_plpa_sockets() 
{

   if (has_core_binding() && _has_topology_information()) {
      int num_sockets, max_socket_id;

      if (plpa_get_socket_info(&num_sockets, &max_socket_id) == 0) {
         return num_sockets;
      } else {
         /* in case of an error we have 0 sockets */
         return 0;
      }
   }

   /* we have 0 cores in case something is wrong */
   return 0;
}
Example #3
0
/****** sge_binding_hlp/get_total_amount_of_plpa_cores() ********************************
*  NAME
*     get_total_amount_of_plpa_cores() -- Fetches the total amount of cores on system. 
*
*  SYNOPSIS
*     int get_total_amount_of_plpa_cores() 
*
*  FUNCTION
*     Returns the total amount of cores per socket. 
*
*  RESULT
*     int - Total amount of cores installed on the system. 
*
*  NOTES
*     MT-NOTE: get_total_amount_of_plpa_cores() is MT safe 
*
*******************************************************************************/
int get_total_amount_of_plpa_cores() 
{
   /* total amount of cores currently active on this system */
   int total_amount_of_cores = 0;
   
   if (has_core_binding() && _has_topology_information()) {
      /* plpa_handle just for an early pre check */ 
      int nr_socket = get_amount_of_plpa_sockets();
      int cntr;
      
      /* get for each socket the amount of cores */
      for (cntr = 0; cntr < nr_socket; cntr++) {
         total_amount_of_cores += get_amount_of_plpa_cores(cntr);
      }
   }
   
   /* in case we got no information about topology we return 0 */
   return total_amount_of_cores;
}
/****** shepherd_binding/bind_process_to_mask() *************************************
*  NAME
*     bind_process_to_mask() -- Binds current process to a given cpuset (mask).
*
*  SYNOPSIS
*     static bool bind_process_to_mask(const hwloc_bitmap_t cpuset)
*
*  FUNCTION
*     Binds current process to a given cpuset. 
*
*  INPUTS
*     const hwloc_bitmap_t cpuset - Processors to bind processes to
*
*  RESULT
*     static bool - true if successful, false otherwise
*
*  NOTES
*     MT-NOTE: bind_process_to_mask() is not MT safe 
*
*******************************************************************************/
static bool bind_process_to_mask(const hwloc_bitmap_t cpuset)
{
   /* we only need core binding capabilites, no topology is required */
   if (!has_core_binding()) return false;
   /* Try strict binding first; fall back to non-strict if it isn't
      available.  */
   if (!hwloc_set_cpubind(sge_hwloc_topology, cpuset, HWLOC_CPUBIND_STRICT) ||
       !hwloc_set_cpubind(sge_hwloc_topology, cpuset, 0)) {
      /* Set the environment variable as for the env type.  Done for
         for conveniece, e.g. with runtimes like GCC's libgomp which
         require an environment variable to be set for thread affinity
         rather than using the core binding in effect.  */
     /* This does not show up in "environment" file!  */
      if (create_binding_env(cpuset) == true)
         shepherd_trace("bind_process_to_mask: SGE_BINDING env var created");
      return true;
      }
   return false;
}
Example #5
0
/****** sge_binding_hlp/get_processor_id() *****************************************
*  NAME
*     get_processor_id() -- Converts a logical socket and core number into a Linux internal. 
*
*  SYNOPSIS
*     int get_processor_id(int socket_number, int core_number) 
*
*  FUNCTION
*     Converts a logical socket and core number (this is beginning at 0 and 
*     without holes) into the Linux internal processor number.  
*
*  INPUTS
*     int socket_number - Socket (starting at 0) to search for core. 
*     int core_number   - Core number (starting at 0) to get id for. 
*
*  RESULT
*     int - Linux internal processor number or negative number on error. 
*
*  NOTES
*     MT-NOTE: get_processor_id() is MT safe 
*
*******************************************************************************/
int get_processor_id(int socket_number, int core_number) 
{
    
   if (has_core_binding() && _has_topology_information()) {
      int proc_id = -1;
      int socket_id = -1;

      if (plpa_get_socket_id(socket_number, &socket_id) != 0) {
         /* unable to retrieve Linux logical socket id */
         return -3;
      }

      if (plpa_map_to_processor_id(socket_id, core_number, &proc_id) == 0) {
         /* everything OK: processor id was set */
         return proc_id;
      } else {
         /* processor id couldn't retrieved */
         return -2; 
      }
   } 
   /* no support for this topology related call */
  return -1;

}
Example #6
0
/****** sge_binding_hlp/get_processor_ids_linux() ******************************
*  NAME
*     get_processor_ids_linux() -- Get internal processor ids for a specific core.
*
*  SYNOPSIS
*     bool get_processor_ids_linux(int socket_number, int core_number, int** 
*     proc_ids, int* amount) 
*
*  FUNCTION
*     Get the Linux internal processor ids for a given core (specified by a socket, 
*     core pair). 
*
*  INPUTS
*     int socket_number - Logical socket number (starting at 0 without holes) 
*     int core_number   - Logical core number on the socket (starting at 0 without holes) 
*
*  OUTPUTS
*     int** proc_ids    - Array of Linux internal processor ids.
*     int* amount       - Size of the proc_ids array.
*
*  RESULT
*     bool - Returns true when processor ids where found otherwise false.
*
*  NOTES
*     MT-NOTE: get_processor_ids_linux() is MT safe 
*
*******************************************************************************/
bool get_processor_ids_linux(int socket_number, int core_number, int** proc_ids, int* amount)
{
   int retval = true;


   if (proc_ids == NULL || (*proc_ids) != NULL || amount == NULL) {
      retval = false;
   } else if (has_core_binding() && _has_topology_information()) {

      /* OS internal socket id and core id of 'socket_number' and 'core_number' */
      int input_core_id   = -1;
      int input_socket_id = -1;

      /* tmp socket and core id of a processor id */
      int core_id   = -1; 
      int socket_id = -1;

      /* the max. Linux processor ID */
      int max_proc_id    = -1;
      /* the number of processors    */
      int num_processors = -1;

      (*amount) = 0;

      /* convert logical socket number into internal socket id */
      if (retval && plpa_get_socket_id(socket_number, &input_socket_id) != 0) {
         /* unable to retrieve Linux logical socket id */
         retval = false;
      }

      /* convert logical core number into internal core id */
      if (retval && plpa_get_core_id(input_socket_id, core_number, &input_core_id) != 0) {
         /* unable to retrieve Linux logical core id  */
         retval = false;
      }

      /* get the max. processor id */
      if (retval && plpa_get_processor_data(PLPA_COUNT_ONLINE, &num_processors, 
                                    &max_proc_id) == 0) {

         /* a possible OS internal processor id */ 
         int proc_cntr;

         /* for all possible processor ids, check if they map to the 
            socket and core id we are searching for */
         for (proc_cntr = 0; proc_cntr <= max_proc_id; proc_cntr++) {

            /* check if processor id is on socket, core */
            if (plpa_map_to_socket_core(proc_cntr, &socket_id, &core_id) != 0) {
               /* not a valid processor id */
               continue;
            }

            if (socket_id == input_socket_id && core_id == input_core_id) {
               /* this OS internal proc id (proc_cntr) points to a 
                  socket, core we are searching for -> in case of hyperthreading 
                  there can be more than one:
                  -> add to the output array */
               (*amount)++;   /* increment the output array size */
               (*proc_ids) = (int *) realloc((*proc_ids), (*amount) * sizeof(int));

               if (*proc_ids == NULL) {
                  /* out of memory */
                  retval = false;
                  (*amount) = 0;
                  break;
               }   
               /* store the processor id as last element in output array */
               (*proc_ids)[(*amount)-1] = proc_cntr;
            }

         }
      }
   }

   if ((*amount) > 0) {
      return true;
   }

   return false;
}
Example #7
0
/****** shepherd_binding/binding_explicit() *****************************************
*  NAME
*     binding_explicit() -- Binds current process to specified CPU cores. 
*
*  SYNOPSIS
*     bool binding_explicit(int* list_of_cores, int camount, int* 
*     list_of_sockets, int samount) 
*
*  FUNCTION
*     Binds the current process to the cores specified by a <socket>,<core>
*     tuple. The tuple is given by a list of sockets and a list of cores. 
*     The elements on the same position of these lists are reflecting 
*     a tuple. Therefore the length of the lists must be the same.
*
*     Binding is currently done on Linux hosts only where the machine topology 
*     can be retrieved with PLPA library. It also does require this library.
*
*  INPUTS
*     int* list_of_sockets - List of sockets in the same order as list of cores. 
*     int samount          - Length of the list of sockets. 
*     int* list_of_cores   - List of cores in the same order as list of sockets. 
*     int camount          - Length of the list of cores. 
*     int type             - Type of binding ( set | env | pe ).
*
*  RESULT
*     bool - true when the current process was bound like specified with the 
*            input parameter
*
*  NOTES
*     MT-NOTE: binding_explicit() is not MT safe 
*
*******************************************************************************/
static bool binding_explicit(const int* list_of_sockets, const int samount, 
   const int* list_of_cores, const int camount, const binding_type_t type)
{
   /* return value: successful bound or not */ 
   bool bound = false;

   /* check if we have exactly the same amount of sockets as cores */
   if (camount != samount) {
      shepherd_trace("binding_explicit: bug: amount of sockets != amount of cores");
      return false;
   }

   if (list_of_sockets == NULL || list_of_cores == NULL) {
      shepherd_trace("binding_explicit: wrong input values");
   }   
   
   /* do only on linux when we have core binding feature in kernel */
   if (has_core_binding() == true) {
      
      if (_has_topology_information()) {
         /* bitmask for processors to turn on and off */
         plpa_cpu_set_t cpuset;  
         /* turn off all processors */
         PLPA_CPU_ZERO(&cpuset);
         /* the internal processor ids selected for the binding mask */
         int* proc_id = NULL;
         int proc_id_size = 0;

         /* processor id counter */
         int pr_id_ctr;

         /* Fetch for each socket,core tuple the processor id. 
            If this is not possible for one do nothing and return false. */ 

         /* go through all socket,core tuples and get the processor id */
         for (pr_id_ctr = 0; pr_id_ctr < camount; pr_id_ctr++) { 

            /* get the processor id */
            /* get the OS internal processor ids */ 
            if (add_proc_ids_linux(list_of_sockets[pr_id_ctr], list_of_cores[pr_id_ctr], 
                                    &proc_id, &proc_id_size) != true) {
               sge_free(&proc_id);
               return false;
            }                       

         }
         /* generate the core binding mask out of the processor id array */
         set_processor_binding_mask(&cpuset, proc_id, proc_id_size); 

         if (type == BINDING_TYPE_PE) {
            
            /* rankfile is created */

         } else if (type == BINDING_TYPE_ENV) {
            /* set the environment variable */
            if (create_binding_env_linux(proc_id, proc_id_size) == true) {
               shepherd_trace("binding_explicit: SGE_BINDING env var created");
            } else {
               shepherd_trace("binding_explicit: problems while creating SGE_BINDING env");
            }
         } else {
            /* do the core binding for the current process with the mask */
            if (bind_process_to_mask((pid_t) 0, cpuset) == true) {
               /* there was an error while binding */ 
               bound = true;
            } else {
               /* couldn't be bound return false */
               shepherd_trace("binding_explicit: bind_process_to_mask was not successful");
            }   
         }

         sge_free(&proc_id);
          
      } else {
         /* has no topology information */
         shepherd_trace("binding_explicit: Linux does not offer topology information");
      }  

   } else {
      /* has no core binding ability */
      shepherd_trace("binding_explicit: host does not support core binding");
   }   

   return bound;
}
/****** shepherd_binding/binding_explicit() *****************************************
*  NAME
*     binding_explicit() -- Binds current process to specified CPU cores. 
*
*  SYNOPSIS
*     bool binding_explicit(int* list_of_cores, int camount, int* 
*     list_of_sockets, int samount) 
*
*  FUNCTION
*     Binds the current process to the cores specified by a <socket>,<core>
*     tuple. The tuple is given by a list of sockets and a list of cores. 
*     The elements on the same position of these lists are reflecting 
*     a tuple. Therefore the length of the lists must be the same.
*
*  INPUTS
*     int* list_of_sockets - List of sockets in the same order as list of cores. 
*     int samount          - Length of the list of sockets. 
*     int* list_of_cores   - List of cores in the same order as list of sockets. 
*     int camount          - Length of the list of cores. 
*     int type             - Type of binding ( set | env | pe ).
*
*  RESULT
*     bool - true when the current process was bound as specified with the
*            input parameter
*
*  NOTES
*     MT-NOTE: binding_explicit() is not MT safe 
*
*******************************************************************************/
static bool binding_explicit(const int* list_of_sockets, const int samount, 
   const int* list_of_cores, const int camount, const binding_type_t type)
{
   /* return value: successful bound or not */ 
   bool bound = false;

#if HAVE_HWLOC
   /* check if we have exactly the same number of sockets as cores */
   if (camount != samount) {
      shepherd_trace("binding_explicit: bug: number of sockets != number of cores");
      return false;
   }

   if (list_of_sockets == NULL || list_of_cores == NULL) {
      shepherd_trace("binding_explicit: wrong input values");
   }   
   
   if (has_core_binding() == true) {
      
      if (has_topology_information()) {
         /* bitmask for processors to turn on and off */
         hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();

         /* processor id counter */
         int pr_id_ctr;

         /* Fetch for each socket,core tuple the processor id. 
            If this is not possible for one do nothing and return false. */ 

         /* go through all socket,core tuples and get the processor id */
         for (pr_id_ctr = 0; pr_id_ctr < camount; pr_id_ctr++) { 
            hwloc_obj_t core =
              hwloc_get_obj_below_by_type(sge_hwloc_topology,
                                          HWLOC_OBJ_SOCKET,
                                          list_of_sockets[pr_id_ctr],
                                          HWLOC_OBJ_CORE,
                                          list_of_cores[pr_id_ctr]);
            if (!core) {
               hwloc_bitmap_free(cpuset);
               return false;
            }
            hwloc_bitmap_or(cpuset, cpuset, core->cpuset);
         }

         if (type == BINDING_TYPE_PE) {
            
            /* rankfile is created */

         } else if (type == BINDING_TYPE_ENV) {
            /* set the environment variable */
            if (create_binding_env(cpuset) == true) {
               shepherd_trace("binding_explicit: SGE_BINDING env var created");
            } else {
               shepherd_trace("binding_explicit: problems while creating SGE_BINDING env");
            }
         } else {
            /* do the core binding for the current process with the mask */
            if (bind_process_to_mask(cpuset) == true) {
               /* there was an error while binding */ 
               bound = true;
            } else {
               /* couldn't be bound return false */
               shepherd_trace("binding_explicit: bind_process_to_mask was not successful");
            }   
         }

         hwloc_bitmap_free(cpuset);
         /* Fixme:  Maybe free topology at this stage, but it probably
            doesn't use a significant amount of space.  */
      } else {
         /* has no topology information */
         shepherd_trace("binding_explicit: no topology information");
      }  

   } else {
      /* has no core binding ability */
      shepherd_trace("binding_explicit: host does not support core binding");
   }   
#endif  /* HAVE_HWLOC */
   return bound;
}
/****** shepherd_binding/binding_set_striding() *************************************
*  NAME
*     binding_set_striding() -- Binds current process to cores.
*
*  SYNOPSIS
*     bool binding_set_striding(int first_socket, int first_core, int
*     number_of_cores, int offset, int stepsize)
*
*  FUNCTION
*     Performs a core binding for the calling process according to the 
*     'striding' strategy. The first core used is specified by first_socket
*     (beginning with 0) and first_core (beginning with 0). If first_core is 
*     greater than available cores on first_socket, the next socket is examined 
*     and first_core is reduced by the skipped cores. If the first_core could 
*     not be found on system (because it was to high) no binding will be done.
*     
*     If the first core was choosen the next one is defined by the step size 'n' 
*     which is incremented to the first core found. If the socket has not the 
*     core (because it was the last core of the socket for example) the next 
*     socket is examined.
*
*     If the system is out of cores and there are still some cores to select 
*     (because of the number_of_cores parameter) no core binding will be performed.
*    
*  INPUTS
*     int first_socket    - first socket to begin with  
*     int first_core      - first core to start with  
*     int number_of_cores - total number of cores to be used
*     int offset          - core offset for first core (increments first core used) 
*     int stepsize        - step size
*     int type            - type of binding (set or env or pe)
*
*  RESULT
*     bool - Returns true if the binding was performed, otherwise false.
*
*  NOTES
*     MT-NOTE: binding_set_striding() is MT safe 
*
*******************************************************************************/
static bool
binding_set_striding(int first_socket, int first_core, int number_of_cores,
                          int offset, int stepsize, const binding_type_t type)
{
   /* n := take every n-th core */ 
   bool bound = false;

#if HAVE_HWLOC
   dstring error = DSTRING_INIT;

   if (has_core_binding() == true) {

      sge_dstring_free(&error);

         /* bitmask for processors to turn on and off */
         hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();

         /* when library offers architecture: 
            - get virtual processor ids in the following manner:
              * on socket "first_socket" choose core number "first_core + offset"
              * then add n: if core is not available go to next socket
              * ...
         */
         if (has_topology_information()) {
            /* number of cores set in processor binding mask */
            int cores_set = 0;
            /* next socket to use */
            int next_socket = first_socket;
            /* next core to use */
            int next_core = first_core + offset;
            /* maximal number of sockets on this system */
            int max_number_of_sockets = get_number_of_sockets();
            hwloc_obj_t core;
            
            /* check if we are already out of range */
            if (next_socket >= max_number_of_sockets) {
               shepherd_trace("binding_set_striding: already out of sockets");
               hwloc_bitmap_free(cpuset);
               return false;
            }   

            while (get_number_of_cores(next_socket) <= next_core) {
               /* move on to next socket - could be that we have to deal only with cores 
                  instead of <socket><core> tuples */
               next_core -= get_number_of_cores(next_socket);
               next_socket++;
               if (next_socket >= max_number_of_sockets) {
                  /* we are out of sockets - we do nothing */
                  shepherd_trace("binding_set_striding: first core: out of sockets");
                  hwloc_bitmap_free(cpuset);
                  return false;
               }
            }  
            core = hwloc_get_obj_below_by_type(sge_hwloc_topology,
                                               HWLOC_OBJ_SOCKET, next_socket,
                                               HWLOC_OBJ_CORE, next_core);
            hwloc_bitmap_or(cpuset, cpuset, core->cpuset);
            
            /* collect the rest of the processor ids */ 
            for (cores_set = 1; cores_set < number_of_cores; cores_set++) {
               /* calculate next_core number */ 
               next_core += stepsize;
               
               /* check if we are already out of range */
               if (next_socket >= max_number_of_sockets) {
                  shepherd_trace("binding_set_striding: out of sockets");
                  hwloc_bitmap_free(cpuset);
                  return false;
               }   

               while (get_number_of_cores(next_socket) <= next_core) {
                  /* move on to next socket - could be that we have to deal only with cores 
                     instead of <socket><core> tuples */
                  next_core -= get_number_of_cores(next_socket);
                  next_socket++;
                  if (next_socket >= max_number_of_sockets) {
                     /* we are out of sockets - we do nothing */
                     shepherd_trace("binding_set_striding: out of sockets!");
                     hwloc_bitmap_free(cpuset);
                     return false;
                  }
                  core = hwloc_get_obj_below_by_type(sge_hwloc_topology,
                                                     HWLOC_OBJ_SOCKET,
                                                     next_socket,
                                                     HWLOC_OBJ_CORE,
                                                     next_core);
                  hwloc_bitmap_or(cpuset, cpuset, core->cpuset);
               }    
                
            } /* collecting processor ids */
           
            if (type == BINDING_TYPE_PE) {
            
               /* rankfile is created: do nothing */

            } else if (type == BINDING_TYPE_ENV) {

               /* set the environment variable */
               if (create_binding_env(cpuset) == true) {
                  shepherd_trace("binding_set_striding: SGE_BINDING env var created");
               } else {
                  shepherd_trace("binding_set_striding: problems while creating SGE_BINDING env");
               }

            } else {
               
               /* bind process to mask */ 
               if (bind_process_to_mask(cpuset) == true) {
                  /* there was an error while binding */ 
                  bound = true;
               }
            }
         
            hwloc_bitmap_free(cpuset);
            
         } else {
            /* setting bitmask without topology information which could 
               not be right? */
            shepherd_trace("binding_set_striding: bitmask without topology information");
            return false;
         }

   } else {
      /* has no core binding feature */
      sge_dstring_free(&error);
      
      return false;
   }
   
#endif  /* HAVE_HWLOC */
   return bound;
}
/****** shepherd_binding/binding_set_linear() ***************************************
*  NAME
*     binding_set_linear() -- Bind current process linear to chunk of cores.
*
*  SYNOPSIS
*     bool binding_set_linear(int first_socket, int first_core, int 
*     number_of_cores, int offset)
*
*  FUNCTION
*     Binds current process (shepherd) to a set of cores. All processes 
*     started by the current process inherit the core binding.
*     
*     The core binding is done in a linear manner, that means that 
*     the process is bound to 'number_of_cores' cores using one core
*     after another starting at socket 'first_socket' (usually 0) and 
*     core = 'first_core' (usually 0) + 'offset'. If the core number 
*     is higher than the number of cores which are provided by socket 
*     'first_socket' then the next socket is taken (the core number 
*      defines how many cores are skiped).
*
*  INPUTS
*     int first_socket    - The first socket (starting at 0) to bind to. 
*     int first_core      - The first core to bind. 
*     int number_of_cores - The number_of_cores of cores to bind to.
*     int offset          - The user specified core number offset. 
*     binding_type_t type - The type of binding ONLY FOR EXECD ( set | env | pe )
*                           
*  RESULT
*     bool - true if binding for current process was done, false if not
*
*  NOTES
*     MT-NOTE: binding_set_linear() is not MT safe 
*
*******************************************************************************/
static bool binding_set_linear(int first_socket, int first_core,
               int number_of_cores, int offset, const binding_type_t type)
{

#if HAVE_HWLOC
   /* sets bitmask in a linear manner        */ 
   /* first core is on exclusive host 0      */ 
   /* first core could be set from scheduler */ 
   /* offset is the first core to start with (makes sense only with
      exclusive host) */
   dstring error = DSTRING_INIT;

   if (has_core_binding() == true) {
      /* bitmask for processors to turn on and off */
      hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
         
      if (has_topology_information()) {
         /* number of cores set in processor binding mask */
         int cores_set;
         /* next socket to use */
         int next_socket = first_socket;
         /* the number of cores of the next socket */
         int socket_number_of_cores;
         /* next core to use */
         int next_core = first_core + offset;
         /* maximal number of sockets on this system */
         int max_number_of_sockets = get_number_of_sockets();
         hwloc_obj_t this_core;

         /* strategy: go to the first_socket and the first_core + offset and 
            fill up socket and go to the next one. */ 
               
         /* TODO maybe better to search for using a core exclusively? */
            
         while (get_number_of_cores(next_socket) <= next_core) {
            /* TODO which kind of warning when first socket does not
               offer this? */
            /* move on to next socket - could be that we have to deal
               only with cores instead of <socket><core> tuples */
            next_core -= get_number_of_cores(next_socket);
            next_socket++;
            if (next_socket >= max_number_of_sockets) {
               /* we are out of sockets - we do nothing */
               hwloc_bitmap_free(cpuset);
               return false;
            }
         }  
         this_core =
            hwloc_get_obj_below_by_type(sge_hwloc_topology,
                                        HWLOC_OBJ_SOCKET, next_socket,
                                        HWLOC_OBJ_CORE, next_core);
         hwloc_bitmap_or(cpuset, cpuset, this_core->cpuset);

         /* collect the other processor ids with the strategy */
         for (cores_set = 1; cores_set < number_of_cores; cores_set++) {
            next_core++;
            /* jump to next socket when it is needed */
            /* maybe the next socket could offer 0 cores (I can't see when, 
               but just to be sure) */
            while ((socket_number_of_cores = get_number_of_cores(next_socket))
                        <= next_core) {
               next_socket++;
               next_core = next_core - socket_number_of_cores;
               if (next_socket >= max_number_of_sockets) {
                  /* we are out of sockets - we do nothing */
                  hwloc_bitmap_free(cpuset);
                  return false;
               }
            }
            this_core =
               hwloc_get_obj_below_by_type(sge_hwloc_topology,
                                           HWLOC_OBJ_SOCKET, next_socket,
                                           HWLOC_OBJ_CORE, next_core);
            hwloc_bitmap_or(cpuset, cpuset, this_core->cpuset);
         }

         /* check what to do with the processor ids (set, env or pe) */
         if (type == BINDING_TYPE_PE) {
               
            /* is done outside */

         } else if (type == BINDING_TYPE_ENV) {
               
            /* set the environment variable                    */
            /* this does not show up in "environment" file !!! */
            if (create_binding_env(cpuset) == true) {
               shepherd_trace("binding_set_linear: SGE_BINDING env var created");
            } else {
               shepherd_trace("binding_set_linear: problems while creating SGE_BINDING env");
            }
             
         } else {

             /* bind SET process to mask */ 
            if (bind_process_to_mask(cpuset) == false) {
               /* there was an error while binding */ 
               hwloc_bitmap_free(cpuset);
               return false;
            }
         }

         hwloc_bitmap_free(cpuset);

      } else {
            
         /* TODO DG strategy without topology information but with 
            working library? */
         shepherd_trace("binding_set_linear: no information about topology");
         return false;
      }
         

   } else {

      shepherd_trace("binding_set_linear: binding not supported: %s",
                     sge_dstring_get_string(&error));

      sge_dstring_free(&error);
   }
#endif  /* HAVE_HWLOC */
   return true;
}