Beispiel #1
0
int geopm_sched_woomp(int num_cpu, cpu_set_t *woomp)
{
    /*! @brief Function that returns a cpuset that has bits set for
               all CPUs enabled for the process which are not used by
               OpenMP.  Rather than returning an empty mask, if all
               CPUs allocated for the process are used by OpenMP, then
               the woomp mask will have all bits set. */

    int err = pthread_once(&g_proc_cpuset_once, geopm_proc_cpuset_once);
    int sched_num_cpu = geopm_sched_num_cpu();
    size_t req_alloc_size = CPU_ALLOC_SIZE(num_cpu);

    if (!err && !g_proc_cpuset) {
        err = ENOMEM;
    }
    if (!err && req_alloc_size < g_proc_cpuset_size) {
        err = EINVAL;
    }
    if (!err) {
        /* Copy the process CPU mask into the output. */
        memcpy(woomp, g_proc_cpuset, g_proc_cpuset_size);
        /* Start an OpenMP parallel region and have each thread clear
           its bit from the mask. */
#ifdef _OPENMP
#pragma omp parallel default(shared)
{
#pragma omp critical
{
        int cpu_index = sched_getcpu();
        if (cpu_index != -1 && cpu_index < num_cpu) {
            /* Clear the bit for this OpenMP thread's CPU. */
            CPU_CLR_S(cpu_index, g_proc_cpuset_size, woomp);
        }
        else {
            err = errno ? errno : GEOPM_ERROR_LOGIC;
        }
} /* end pragma omp critical */
} /* end pragma omp parallel */
#endif /* _OPENMP */
    }
    if (!err) {
        for (int i = sched_num_cpu; i < num_cpu; ++i) {
            CPU_CLR_S(i, req_alloc_size, woomp);
        }
    }
    if (err || CPU_COUNT_S(g_proc_cpuset_size, woomp) == 0) {
        /* If all CPUs are used by the OpenMP gang, then leave the
           mask open and allow the Linux scheduler to choose. */
        for (int i = 0; i < num_cpu; ++i) {
            CPU_SET_S(i, g_proc_cpuset_size, woomp);
        }
    }
    return err;
}
Beispiel #2
0
int geopm_sched_proc_cpuset(int num_cpu, cpu_set_t *proc_cpuset)
{
    int err = pthread_once(&g_proc_cpuset_once, geopm_proc_cpuset_once);
    int sched_num_cpu = geopm_sched_num_cpu();
    size_t cpuset_size = CPU_ALLOC_SIZE(num_cpu);
    if (!err && cpuset_size < g_proc_cpuset_size) {
        err = GEOPM_ERROR_INVALID;
    }
    if (!err) {
        memcpy(proc_cpuset, g_proc_cpuset, g_proc_cpuset_size);
        for (int i = sched_num_cpu; i < num_cpu; ++i) {
            CPU_CLR_S(i, cpuset_size, proc_cpuset);
        }
    }
    return err;
}
Beispiel #3
0
bool
gomp_affinity_remove_cpu (void *p, unsigned long num)
{
  cpu_set_t *cpusetp = (cpu_set_t *) p;
  if (num >= 8 * gomp_cpuset_size)
    {
      gomp_error ("Logical CPU number %lu out of range", num);
      return false;
    }
  if (!CPU_ISSET_S (num, gomp_cpuset_size, cpusetp))
    {
      gomp_error ("Logical CPU %lu to be removed is not in the set", num);
      return false;
    }
  CPU_CLR_S (num, gomp_cpuset_size, cpusetp);
  return true;
}
Beispiel #4
0
bool
gomp_affinity_init_level (int level, unsigned long count, bool quiet)
{
  unsigned long i, max = 8 * gomp_cpuset_size;

  if (gomp_cpusetp)
    {
      unsigned long maxcount
	= gomp_cpuset_popcount (gomp_cpuset_size, gomp_cpusetp);
      if (count > maxcount)
	count = maxcount;
    }
  gomp_places_list = gomp_affinity_alloc (count, quiet);
  gomp_places_list_len = 0;
  if (gomp_places_list == NULL)
    return false;
  /* SMT (threads).  */
  if (level == 1)
    {
      for (i = 0; i < max && gomp_places_list_len < count; i++)
	if (CPU_ISSET_S (i, gomp_cpuset_size, gomp_cpusetp))
	  {
	    gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
	    gomp_affinity_add_cpus (gomp_places_list[gomp_places_list_len],
				    i, 1, 0, true);
	    ++gomp_places_list_len;
	  }
      return true;
    }
  else
    {
      char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
			"thread_siblings_list") + 3 * sizeof (unsigned long)];
      size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1;
      cpu_set_t *copy = gomp_alloca (gomp_cpuset_size);
      FILE *f;
      char *line = NULL;
      size_t linelen = 0;

      memcpy (name, "/sys/devices/system/cpu/cpu", prefix_len);
      memcpy (copy, gomp_cpusetp, gomp_cpuset_size);
      for (i = 0; i < max && gomp_places_list_len < count; i++)
	if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
	  {
	    sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
		     i, level == 2 ? "thread" : "core");
	    f = fopen (name, "r");
	    if (f != NULL)
	      {
		if (getline (&line, &linelen, f) > 0)
		  {
		    char *p = line;
		    bool seen_i = false;
		    void *pl = gomp_places_list[gomp_places_list_len];
		    gomp_affinity_init_place (pl);
		    while (*p && *p != '\n')
		      {
			unsigned long first, last;
			errno = 0;
			first = strtoul (p, &p, 10);
			if (errno)
			  break;
			last = first;
			if (*p == '-')
			  {
			    errno = 0;
			    last = strtoul (p + 1, &p, 10);
			    if (errno || last < first)
			      break;
			  }
			for (; first <= last; first++)
			  if (CPU_ISSET_S (first, gomp_cpuset_size, copy)
			      && gomp_affinity_add_cpus (pl, first, 1, 0,
							 true))
			    {
			      CPU_CLR_S (first, gomp_cpuset_size, copy);
			      if (first == i)
				seen_i = true;
			    }
			if (*p == ',')
			  ++p;
		      }
		    if (seen_i)
		      gomp_places_list_len++;
		  }
		fclose (f);
	      }
	  }
      if (gomp_places_list_len == 0)
	{
	  if (!quiet)
	    gomp_error ("Error reading %s topology",
			level == 2 ? "core" : "socket");
	  free (gomp_places_list);
	  gomp_places_list = NULL;
	  return false;
	}
      return true;
    }
  return false;
}