void gomp_init_affinity (void) { cpu_set_t cpuset; size_t idx, widx; if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset), &cpuset)) { gomp_error ("could not get CPU affinity set"); free (gomp_cpu_affinity); gomp_cpu_affinity = NULL; gomp_cpu_affinity_len = 0; return; } for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++) if (gomp_cpu_affinity[idx] < CPU_SETSIZE && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset)) gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx]; if (widx == 0) { gomp_error ("no CPUs left for affinity setting"); free (gomp_cpu_affinity); gomp_cpu_affinity = NULL; gomp_cpu_affinity_len = 0; return; } gomp_cpu_affinity_len = widx; CPU_ZERO (&cpuset); CPU_SET (gomp_cpu_affinity[0], &cpuset); pthread_setaffinity_np (pthread_self (), sizeof (cpuset), &cpuset); affinity_counter = 1; }
bool gomp_affinity_add_cpus (void *p, unsigned long num, unsigned long len, long stride, bool quiet) { cpu_set_t *cpusetp = (cpu_set_t *) p; unsigned long max = 8 * gomp_cpuset_size; for (;;) { if (num >= max) { if (!quiet) gomp_error ("Logical CPU number %lu out of range", num); return false; } CPU_SET_S (num, gomp_cpuset_size, cpusetp); if (--len == 0) return true; if ((stride < 0 && num + stride > num) || (stride > 0 && num + stride < num)) { if (!quiet) gomp_error ("Logical CPU number %lu+%ld out of range", num, stride); return false; } num += stride; } }
static void parse_boolean (const char *name, bool *value) { const char *env; env = getenv (name); if (env == NULL) return; while (isspace ((unsigned char) *env)) ++env; if (strncasecmp (env, "true", 4) == 0) { *value = true; env += 4; } else if (strncasecmp (env, "false", 5) == 0) { *value = false; env += 5; } else env = "X"; while (isspace ((unsigned char) *env)) ++env; if (*env != '\0') gomp_error ("Invalid value for environment variable %s", name); }
static bool parse_unsigned_long (const char *name, unsigned long *pvalue) { char *env, *end; unsigned long value; env = getenv (name); if (env == NULL) return false; while (isspace ((unsigned char) *env)) ++env; if (*env == '\0') goto invalid; errno = 0; value = strtoul (env, &end, 10); if (errno || (long) value <= 0) goto invalid; while (isspace ((unsigned char) *end)) ++end; if (*end != '\0') goto invalid; *pvalue = value; return true; invalid: gomp_error ("Invalid value for environment variable %s", name); return false; }
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; }
bool gomp_affinity_init_level (int level, unsigned long count, bool quiet) { (void) level; (void) count; (void) quiet; if (!quiet) gomp_error ("Affinity not supported on this configuration"); return NULL; }
initialize_env (void) { unsigned long stacksize; /* Do a compile time check that mkomp_h.pl did good job. */ omp_check_defines (); parse_schedule (); parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var); parse_boolean ("OMP_NESTED", &gomp_nest_var); if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var)) gomp_init_num_threads (); /* Not strictly environment related, but ordering constructors is tricky. */ pthread_attr_init (&gomp_thread_attr); pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED); if (parse_unsigned_long ("GOMP_STACKSIZE", &stacksize)) { int err; stacksize *= 1024; err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize); #ifdef PTHREAD_STACK_MIN if (err == EINVAL) { if (stacksize < PTHREAD_STACK_MIN) gomp_error ("Stack size less than minimum of %luk", PTHREAD_STACK_MIN / 1024ul + (PTHREAD_STACK_MIN % 1024 != 0)); else gomp_error ("Stack size larger than system limit"); } else #endif if (err != 0) gomp_error ("Stack size change failed: %s", strerror (err)); } }
bool gomp_affinity_finalize_place_list (bool quiet) { unsigned long i, j; for (i = 0, j = 0; i < gomp_places_list_len; i++) { cpu_set_t *cpusetp = (cpu_set_t *) gomp_places_list[i]; bool nonempty = false; #ifdef CPU_AND_S CPU_AND_S (gomp_cpuset_size, cpusetp, cpusetp, gomp_cpusetp); nonempty = gomp_cpuset_popcount (gomp_cpuset_size, cpusetp) != 0; #else unsigned long k, max = gomp_cpuset_size / sizeof (cpusetp->__bits[0]); for (k = 0; k < max; k++) if ((cpusetp->__bits[k] &= gomp_cpusetp->__bits[k]) != 0) nonempty = true; #endif if (nonempty) gomp_places_list[j++] = gomp_places_list[i]; } if (j == 0) { if (!quiet) gomp_error ("None of the places contain usable logical CPUs"); return false; } else if (j < gomp_places_list_len) { if (!quiet) gomp_error ("Number of places reduced from %ld to %ld because some " "places didn't contain any usable logical CPUs", gomp_places_list_len, j); gomp_places_list_len = j; } return true; }
bool gomp_affinity_copy_place (void *p, void *q, long stride) { unsigned long i, max = 8 * gomp_cpuset_size; cpu_set_t *destp = (cpu_set_t *) p; cpu_set_t *srcp = (cpu_set_t *) q; CPU_ZERO_S (gomp_cpuset_size, destp); for (i = 0; i < max; i++) if (CPU_ISSET_S (i, gomp_cpuset_size, srcp)) { if ((stride < 0 && i + stride > i) || (stride > 0 && (i + stride < i || i + stride >= max))) { gomp_error ("Logical CPU number %lu+%ld out of range", i, stride); return false; } CPU_SET_S (i + stride, gomp_cpuset_size, destp); } return true; }
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; }
static void parse_schedule (void) { char *env, *end; unsigned long value; env = getenv ("OMP_SCHEDULE"); if (env == NULL) return; while (isspace ((unsigned char) *env)) ++env; if (strncasecmp (env, "static", 6) == 0) { gomp_run_sched_var = GFS_STATIC; env += 6; } else if (strncasecmp (env, "dynamic", 7) == 0) { gomp_run_sched_var = GFS_DYNAMIC; env += 7; } else if (strncasecmp (env, "guided", 6) == 0) { gomp_run_sched_var = GFS_GUIDED; env += 6; } else goto unknown; while (isspace ((unsigned char) *env)) ++env; if (*env == '\0') return; if (*env++ != ',') goto unknown; while (isspace ((unsigned char) *env)) ++env; if (*env == '\0') goto invalid; errno = 0; value = strtoul (env, &end, 10); if (errno) goto invalid; while (isspace ((unsigned char) *end)) ++end; if (*end != '\0') goto invalid; gomp_run_sched_chunk = value; return; unknown: gomp_error ("Unknown value for environment variable OMP_SCHEDULE"); return; invalid: gomp_error ("Invalid value for chunk size in " "environment variable OMP_SCHEDULE"); return; }