Exemple #1
0
int main(int argc, const char * const argv[])
{
  hwloc_topology_t topo;
  hwloc_obj_t pu;
  const char *basedir;
  const char *callname;
  char *path;
  size_t pathlen;
  unsigned idx = (unsigned) -1;
  int err;
  int ret = EXIT_SUCCESS;

  callname = argv[0];
  argc--; argv++;

  hwloc_utils_check_api_version(callname);

  if (!hwloc_have_x86_cpuid()) {
    fprintf(stderr, "CPUID not supported.\n");
    ret = EXIT_FAILURE;
    goto out;
  }

  while (argc > 0 && argv[0][0] == '-' && argv[0][1] != '\0') {
    if (argc >= 2 && !strcmp(argv[0], "-c")) {
      idx = atoi(argv[1]);
      argc -= 2;
      argv += 2;
    } else if (argc >= 1 && (!strcmp(argv[0], "-s") || !strcmp(argv[0], "--silent"))) {
      verbose--;
      argc--;
      argv++;
    } else if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
      usage(callname, stdout);
      goto out;
    } else {
      usage(callname, stderr);
      ret = EXIT_FAILURE;
      goto out;
    }
  }

  basedir = "./cpuid";
  if (argc >= 1)
    basedir = argv[0];

  if (!getenv("HWLOC_COMPONENTS"))
    putenv((char *) "HWLOC_COMPONENTS=no_os,stop");

  hwloc_topology_init(&topo);
  hwloc_topology_set_all_types_filter(topo, HWLOC_TYPE_FILTER_KEEP_NONE);
  err = hwloc_topology_load(topo);
  if (err < 0) {
    fprintf(stderr, "Failed to load topology\n");
    ret = EXIT_FAILURE;
    goto out;
  }

  if (!hwloc_topology_is_thissystem(topo)) {
    fprintf(stderr, "%s must run on the current system topology, while this topology doesn't come from this system.\n", callname);
    ret = EXIT_FAILURE;
    goto out;
  }

  if (!strcmp(basedir, "-")) {
    if (verbose)
      printf("Gathering on stdout ...\n");
    if (idx == (unsigned) -1) {
      fprintf(stderr, "Cannot gather multiple PUs on stdout.\n");
      ret = EXIT_FAILURE;
      goto out;
    }
    path = NULL;
    pathlen = 0;
  } else {
    err = mkdir(basedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
    if (err < 0) {
      if (access(basedir, X_OK|W_OK) < 0) {
	fprintf(stderr, "Could not create/open destination directory %s\n", basedir);
	ret = EXIT_FAILURE;
	goto out_with_topo;
      }
    }
    if (verbose)
      printf("Gathering in directory %s ...\n", basedir);

    pathlen = strlen(basedir) + 20; /* for '/pu%u' or '/hwloc-cpuid-info' */
    path = malloc(pathlen);
  }

  if (idx == (unsigned) -1) {
    FILE *file;
    pu = NULL;
    while ((pu = hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_PU, pu)) != NULL) {
      idx = pu->os_index;
      if (path)
	snprintf(path, pathlen, "%s/pu%u", basedir, idx);
      dump_one_proc(topo, pu, path);
    }

    snprintf(path, pathlen, "%s/hwloc-cpuid-info", basedir);
    file = fopen(path, "w");
    if (file) {
      fprintf(file, "Architecture: x86\n");
      fclose(file);
      if (verbose)
	printf("Summary written to %s\n", path);
    } else {
      fprintf(stderr, "Failed to open summary file '%s' for writing: %s\n", path, strerror(errno));
    }
  } else {
    pu = hwloc_get_pu_obj_by_os_index(topo, idx);
    if (!pu) {
      fprintf(stderr, "Cannot find PU P#%u\n", idx);
      ret = EXIT_FAILURE;
      goto out_with_path;
    } else {
      if (path)
        snprintf(path, pathlen, "%s/pu%u", basedir, idx);
      dump_one_proc(topo, pu, path);
    }
  }

  if (verbose)
    printf("\n"
	   "WARNING: Do not post these files on a public list or website unless you\n"
	   "WARNING: are sure that no information about this platform is sensitive.\n");

 out_with_path:
  free(path);
 out_with_topo:
  hwloc_topology_destroy(topo);
 out:
  return ret;
}
Exemple #2
0
int main(int argc, char *argv[])
{
    const struct hwloc_topology_support *support;
    hwloc_topology_t topology;
    hwloc_const_bitmap_t topocpuset;
    hwloc_bitmap_t cpuset;
    unsigned long flags = 0;
    DIR *dir;
    struct dirent *dirent;
    int show_all = 0;
    int show_threads = 0;
    int get_last_cpu_location = 0;
    char *callname;
    char *pidcmd = NULL;
    int err;
    int opt;

    callname = strrchr(argv[0], '/');
    if (!callname)
        callname = argv[0];
    else
        callname++;
    /* skip argv[0], handle options */
    argc--;
    argv++;

    hwloc_utils_check_api_version(callname);

    while (argc >= 1) {
        opt = 0;
        if (!strcmp(argv[0], "-a"))
            show_all = 1;
        else if (!strcmp(argv[0], "-l") || !strcmp(argv[0], "--logical")) {
            logical = 1;
        } else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--physical")) {
            logical = 0;
        } else if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--cpuset")) {
            show_cpuset = 1;
        } else if (!strcmp(argv[0], "-e") || !strncmp(argv[0], "--get-last-cpu-location", 10)) {
            get_last_cpu_location = 1;
        } else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--threads")) {
#ifdef HWLOC_LINUX_SYS
            show_threads = 1;
#else
            fprintf (stderr, "Listing threads is currently only supported on Linux\n");
#endif
        } else if (!strcmp (argv[0], "--whole-system")) {
            flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM;
        } else if (!strcmp (argv[0], "--pid-cmd")) {
            if (argc < 2) {
                usage(callname, stdout);
                exit(EXIT_FAILURE);
            }
            pidcmd = argv[1];
            opt = 1;
        } else {
            fprintf (stderr, "Unrecognized option: %s\n", argv[0]);
            usage (callname, stderr);
            exit(EXIT_FAILURE);
        }
        argc -= opt+1;
        argv += opt+1;
    }

    err = hwloc_topology_init(&topology);
    if (err)
        goto out;

    hwloc_topology_set_flags(topology, flags);

    err = hwloc_topology_load(topology);
    if (err)
        goto out_with_topology;

    support = hwloc_topology_get_support(topology);

    if (get_last_cpu_location) {
        if (!support->cpubind->get_proc_last_cpu_location)
            goto out_with_topology;
    } else {
        if (!support->cpubind->get_proc_cpubind)
            goto out_with_topology;
    }

    topocpuset = hwloc_topology_get_topology_cpuset(topology);

    dir  = opendir("/proc");
    if (!dir)
        goto out_with_topology;

    cpuset = hwloc_bitmap_alloc();
    if (!cpuset)
        goto out_with_dir;

    while ((dirent = readdir(dir))) {
        long pid_number;
        hwloc_pid_t pid;
        char pidoutput[1024];
        char *end;
        char name[64] = "";
        /* management of threads */
        unsigned boundthreads = 0, i;
        long *tids = NULL; /* NULL if process is not threaded */
        hwloc_bitmap_t *tidcpusets = NULL;

        pid_number = strtol(dirent->d_name, &end, 10);
        if (*end)
            /* Not a number */
            continue;

        pid = hwloc_pid_from_number(pid_number, 0);

#ifdef HWLOC_LINUX_SYS
        {
            unsigned pathlen = 6 + strlen(dirent->d_name) + 1 + 7 + 1;
            char *path;
            int file;
            ssize_t n;

            path = malloc(pathlen);
            snprintf(path, pathlen, "/proc/%s/cmdline", dirent->d_name);
            file = open(path, O_RDONLY);
            free(path);

            if (file >= 0) {
                n = read(file, name, sizeof(name) - 1);
                close(file);

                if (n <= 0)
                    /* Ignore kernel threads and errors */
                    continue;

                name[n] = 0;
            }
        }
#endif /* HWLOC_LINUX_SYS */

        if (show_threads) {
#ifdef HWLOC_LINUX_SYS
            /* check if some threads must be displayed */
            unsigned pathlen = 6 + strlen(dirent->d_name) + 1 + 4 + 1;
            char *path;
            DIR *taskdir;

            path = malloc(pathlen);
            snprintf(path, pathlen, "/proc/%s/task", dirent->d_name);
            taskdir = opendir(path);
            if (taskdir) {
                struct dirent *taskdirent;
                long tid;
                unsigned n = 0;
                /* count threads */
                while ((taskdirent = readdir(taskdir))) {
                    tid = strtol(taskdirent->d_name, &end, 10);
                    if (*end)
                        /* Not a number */
                        continue;
                    n++;
                }
                if (n > 1) {
                    /* if there's more than one thread, see if some are bound */
                    tids = malloc(n * sizeof(*tids));
                    tidcpusets = calloc(n+1, sizeof(*tidcpusets));
                    if (tids && tidcpusets) {
                        /* reread the directory but gather info now */
                        rewinddir(taskdir);
                        i = 0;
                        while ((taskdirent = readdir(taskdir))) {
                            tid = strtol(taskdirent->d_name, &end, 10);
                            if (*end)
                                /* Not a number */
                                continue;
                            if (get_last_cpu_location) {
                                if (hwloc_linux_get_tid_last_cpu_location(topology, tid, cpuset))
                                    continue;
                            } else {
                                if (hwloc_linux_get_tid_cpubind(topology, tid, cpuset))
                                    continue;
                            }
                            hwloc_bitmap_and(cpuset, cpuset, topocpuset);
                            tids[i] = tid;
                            tidcpusets[i] = hwloc_bitmap_dup(cpuset);
                            i++;
                            if (hwloc_bitmap_iszero(cpuset))
                                continue;
                            if (hwloc_bitmap_isequal(cpuset, topocpuset) && !show_all)
                                continue;
                            boundthreads++;
                        }
                    } else {
                        /* failed to alloc, behave as if there were no threads */
                        free(tids);
                        tids = NULL;
                        free(tidcpusets);
                        tidcpusets = NULL;
                    }
                }
                closedir(taskdir);
            }
#endif /* HWLOC_LINUX_SYS */
        }

        if (get_last_cpu_location) {
            if (hwloc_get_proc_last_cpu_location(topology, pid, cpuset, 0))
                continue;
        } else {
            if (hwloc_get_proc_cpubind(topology, pid, cpuset, 0))
                continue;
        }

        hwloc_bitmap_and(cpuset, cpuset, topocpuset);
        if (hwloc_bitmap_iszero(cpuset))
            continue;

        /* don't print anything if the process isn't bound and if no threads are bound and if not showing all */
        if (hwloc_bitmap_isequal(cpuset, topocpuset) && (!tids || !boundthreads) && !show_all)
            continue;

        pidoutput[0] = '\0';
        if (pidcmd) {
            char *cmd;
            FILE *file;
            cmd = malloc(strlen(pidcmd)+1+5+2+1);
            sprintf(cmd, "%s %u", pidcmd, pid);
            file = popen(cmd, "r");
            if (file) {
                if (fgets(pidoutput, sizeof(pidoutput), file)) {
                    end = strchr(pidoutput, '\n');
                    if (end)
                        *end = '\0';
                }
                pclose(file);
            }
            free(cmd);
        }

        /* print the process */
        print_task(topology, pid_number, name, cpuset, pidoutput[0] == '\0' ? NULL : pidoutput, 0);
        if (tids)
            /* print each tid we found (it's tidcpuset isn't NULL anymore) */
            for(i=0; tidcpusets[i] != NULL; i++) {
                print_task(topology, tids[i], "", tidcpusets[i], NULL, 1);
                hwloc_bitmap_free(tidcpusets[i]);
            }

        /* free threads stuff */
        free(tidcpusets);
        free(tids);
    }

    err = 0;
    hwloc_bitmap_free(cpuset);

out_with_dir:
    closedir(dir);
out_with_topology:
    hwloc_topology_destroy(topology);
out:
    return err;
}
Exemple #3
0
int main(int argc, char *argv[])
{
  hwloc_topology_t topology;
  int loaded = 0;
  int depth;
  hwloc_bitmap_t cpubind_set, membind_set;
  int got_cpubind = 0, got_membind = 0;
  int working_on_cpubind = 1; /* membind if 0 */
  int get_binding = 0;
  int use_nodeset = 0;
  int get_last_cpu_location = 0;
  unsigned long flags = 0;
  int force = 0;
  int single = 0;
  int verbose = 0;
  int only_hbm = -1;
  int logical = 1;
  int taskset = 0;
  unsigned cpubind_flags = 0;
  hwloc_membind_policy_t membind_policy = HWLOC_MEMBIND_BIND;
  int got_mempolicy = 0;
  unsigned membind_flags = 0;
  int opt;
  int ret;
  int pid_number = -1;
  int tid_number = -1;
  hwloc_pid_t pid = 0; /* only valid when pid_number > 0, but gcc-4.8 still reports uninitialized warnings */
  char *callname;
  struct hwloc_calc_location_context_s lcontext;
  struct hwloc_calc_set_context_s scontext;

  callname = argv[0];
  /* skip argv[0], handle options */
  argv++;
  argc--;

  hwloc_utils_check_api_version(callname);

  cpubind_set = hwloc_bitmap_alloc();
  membind_set = hwloc_bitmap_alloc();

  /* don't load now, in case some options change the config before the topology is actually used */
#define LOADED() (loaded)
#define ENSURE_LOADED() do { \
  if (!loaded) { \
    hwloc_topology_init(&topology); \
    hwloc_topology_set_all_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_ALL); \
    hwloc_topology_set_flags(topology, flags); \
    hwloc_topology_load(topology); \
    depth = hwloc_topology_get_depth(topology); \
    loaded = 1; \
  } \
} while (0)

  while (argc >= 1) {
    if (!strcmp(argv[0], "--")) {
      argc--;
      argv++;
      break;
    }

    opt = 0;

    if (*argv[0] == '-') {
      if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) {
	verbose++;
	goto next;
      }
      if (!strcmp(argv[0], "-q") || !strcmp(argv[0], "--quiet")) {
	verbose--;
	goto next;
      }
      if (!strcmp(argv[0], "--help")) {
        usage("hwloc-bind", stdout);
	return EXIT_SUCCESS;
      }
      if (!strcmp(argv[0], "--single")) {
	single = 1;
	goto next;
      }
      if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--force")) {
	force = 1;
	goto next;
      }
      if (!strcmp(argv[0], "--strict")) {
	cpubind_flags |= HWLOC_CPUBIND_STRICT;
	membind_flags |= HWLOC_MEMBIND_STRICT;
	goto next;
      }
      if (!strcmp(argv[0], "--pid")) {
        if (argc < 2) {
          usage ("hwloc-bind", stderr);
          exit(EXIT_FAILURE);
        }
        pid_number = atoi(argv[1]);
        opt = 1;
        goto next;
      }
#ifdef HWLOC_LINUX_SYS
      if (!strcmp(argv[0], "--tid")) {
        if (argc < 2) {
          usage ("hwloc-bind", stderr);
          exit(EXIT_FAILURE);
        }
        tid_number = atoi(argv[1]);
        opt = 1;
        goto next;
      }
#endif
      if (!strcmp (argv[0], "--version")) {
	printf("%s %s\n", callname, HWLOC_VERSION);
	exit(EXIT_SUCCESS);
      }
      if (!strcmp(argv[0], "-l") || !strcmp(argv[0], "--logical")) {
        logical = 1;
        goto next;
      }
      if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--physical")) {
        logical = 0;
        goto next;
      }
      if (!strcmp(argv[0], "--taskset")) {
        taskset = 1;
        goto next;
      }
      if (!strcmp (argv[0], "-e") || !strncmp (argv[0], "--get-last-cpu-location", 10)) {
	get_last_cpu_location = 1;
	goto next;
      }
      if (!strcmp (argv[0], "--get")) {
	get_binding = 1;
	goto next;
      }
      if (!strcmp (argv[0], "--nodeset")) {
	use_nodeset = 1;
	goto next;
      }
      if (!strcmp (argv[0], "--cpubind")) {
	working_on_cpubind = 1;
	goto next;
      }
      if (!strcmp (argv[0], "--membind")) {
	working_on_cpubind = 0;
	goto next;
      }
      if (!strcmp (argv[0], "--mempolicy")) {
	if (!strncmp(argv[1], "default", 2))
	  membind_policy = HWLOC_MEMBIND_DEFAULT;
	else if (!strncmp(argv[1], "firsttouch", 2))
	  membind_policy = HWLOC_MEMBIND_FIRSTTOUCH;
	else if (!strncmp(argv[1], "bind", 2))
	  membind_policy = HWLOC_MEMBIND_BIND;
	else if (!strncmp(argv[1], "interleave", 2))
	  membind_policy = HWLOC_MEMBIND_INTERLEAVE;
	else if (!strncmp(argv[1], "nexttouch", 2))
	  membind_policy = HWLOC_MEMBIND_NEXTTOUCH;
	else {
	  fprintf(stderr, "Unrecognized memory binding policy %s\n", argv[1]);
          usage ("hwloc-bind", stderr);
          exit(EXIT_FAILURE);
	}
	got_mempolicy = 1;
	opt = 1;
	goto next;
      }
      if (!strcmp(argv[0], "--hbm")) {
	only_hbm = 1;
	goto next;
      }
      if (!strcmp(argv[0], "--no-hbm")) {
	only_hbm = 0;
	goto next;
      }
      if (!strcmp (argv[0], "--whole-system")) {
	if (loaded) {
	  fprintf(stderr, "Input option %s disallowed after options using the topology\n", argv[0]);
	  exit(EXIT_FAILURE);
	}
	flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM;
	goto next;
      }
      if (!strcmp (argv[0], "--restrict")) {
	hwloc_bitmap_t restrictset;
	int err;
	if (argc < 2) {
	  usage (callname, stdout);
	  exit(EXIT_FAILURE);
	}
	restrictset = hwloc_bitmap_alloc();
	hwloc_bitmap_sscanf(restrictset, argv[1]);
	ENSURE_LOADED();
	err = hwloc_topology_restrict (topology, restrictset, 0);
	if (err) {
	  perror("Restricting the topology");
	  /* FALLTHRU */
	}
	hwloc_bitmap_free(restrictset);
	argc--;
	argv++;
	goto next;
      }

      fprintf (stderr, "Unrecognized option: %s\n", argv[0]);
      usage("hwloc-bind", stderr);
      return EXIT_FAILURE;
    }

    ENSURE_LOADED();

    lcontext.topology = topology;
    lcontext.topodepth = depth;
    lcontext.only_hbm = only_hbm;
    lcontext.logical = logical;
    lcontext.verbose = verbose;
    scontext.nodeset_input = use_nodeset;
    scontext.nodeset_output = working_on_cpubind ? 0 : 1;
    scontext.output_set = working_on_cpubind ? cpubind_set : membind_set;
    ret = hwloc_calc_process_location_as_set(&lcontext, &scontext, argv[0]);
    if (ret < 0) {
      if (verbose > 0)
	fprintf(stderr, "assuming the command starts at %s\n", argv[0]);
      break;
    }
    if (working_on_cpubind)
      got_cpubind = 1;
    else
      got_membind = 1;

  next:
    argc -= opt+1;
    argv += opt+1;
  }

  ENSURE_LOADED();

  if (pid_number > 0 && tid_number > 0) {
    fprintf(stderr, "cannot operate both on tid and pid\n");
    return EXIT_FAILURE;
  }

  if (pid_number > 0) {
    pid = hwloc_pid_from_number(pid_number, !(get_binding || get_last_cpu_location));
    /* no need to set_pid()
     * the doc just says we're operating on pid, not that we're retrieving the topo/cpuset as seen from inside pid
     */
  }

  if (get_last_cpu_location && !working_on_cpubind) {
    fprintf(stderr, "Options --membind and --get-last-cpu-location cannot be combined.\n");
    return EXIT_FAILURE;
  }
  if ((get_binding || get_last_cpu_location) && (got_cpubind || got_membind)) {
    /* doesn't work because get_binding/get_last_cpu_location overwrites cpubind_set */
    fprintf(stderr, "Cannot display and set binding at the same time.\n");
    return EXIT_FAILURE;
  }

  if (get_binding || get_last_cpu_location) {
    char *s;
    const char *policystr = NULL;
    int err;
    if (working_on_cpubind) {
      if (get_last_cpu_location) {
	if (pid_number > 0)
	  err = hwloc_get_proc_last_cpu_location(topology, pid, cpubind_set, 0);
#ifdef HWLOC_LINUX_SYS
	else if (tid_number > 0)
	  err = hwloc_linux_get_tid_last_cpu_location(topology, tid_number, cpubind_set);
#endif
	else
	  err = hwloc_get_last_cpu_location(topology, cpubind_set, 0);
      } else {
	if (pid_number > 0)
	  err = hwloc_get_proc_cpubind(topology, pid, cpubind_set, 0);
#ifdef HWLOC_LINUX_SYS
	else if (tid_number > 0)
	  err = hwloc_linux_get_tid_cpubind(topology, tid_number, cpubind_set);
#endif
	else
	  err = hwloc_get_cpubind(topology, cpubind_set, 0);
      }
      if (err) {
	const char *errmsg = strerror(errno);
	if (pid_number > 0)
	  fprintf(stderr, "hwloc_get_proc_%s %d failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", pid_number, errno, errmsg);
	else if (tid_number > 0)
	  fprintf(stderr, "hwloc_get_tid_%s %d failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", tid_number, errno, errmsg);
	else
	  fprintf(stderr, "hwloc_get_%s failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", errno, errmsg);
	return EXIT_FAILURE;
      }
      if (use_nodeset) {
	hwloc_bitmap_t nset = hwloc_bitmap_alloc();
	hwloc_cpuset_to_nodeset(topology, cpubind_set, nset);
	if (taskset)
	  hwloc_bitmap_taskset_asprintf(&s, nset);
	else
	  hwloc_bitmap_asprintf(&s, nset);
	hwloc_bitmap_free(nset);
      } else {
	if (taskset)
	  hwloc_bitmap_taskset_asprintf(&s, cpubind_set);
	else
	  hwloc_bitmap_asprintf(&s, cpubind_set);
      }

      } else {
      hwloc_membind_policy_t policy;
      if (pid_number > 0) {
	err = hwloc_get_proc_membind(topology, pid, membind_set, &policy, use_nodeset ? HWLOC_MEMBIND_BYNODESET : 0);
      } else if (tid_number > 0) {
	err = -1; errno = ENOSYS;
      } else {
	err = hwloc_get_membind(topology, membind_set, &policy, use_nodeset ? HWLOC_MEMBIND_BYNODESET : 0);
      }
      if (err) {
	const char *errmsg = strerror(errno);
        if (pid_number > 0)
          fprintf(stderr, "hwloc_get_proc_membind %d failed (errno %d %s)\n", pid_number, errno, errmsg);
        else
	  fprintf(stderr, "hwloc_get_membind failed (errno %d %s)\n", errno, errmsg);
	return EXIT_FAILURE;
      }
      if (taskset)
	hwloc_bitmap_taskset_asprintf(&s, membind_set);
      else
	hwloc_bitmap_asprintf(&s, membind_set);
      switch (policy) {
      case HWLOC_MEMBIND_FIRSTTOUCH: policystr = "firsttouch"; break;
      case HWLOC_MEMBIND_BIND: policystr = "bind"; break;
      case HWLOC_MEMBIND_INTERLEAVE: policystr = "interleave"; break;
      case HWLOC_MEMBIND_NEXTTOUCH: policystr = "nexttouch"; break;
      default: fprintf(stderr, "unknown memory policy %d\n", policy); assert(0); break;
      }
    }
    if (policystr)
      printf("%s (%s)\n", s, policystr);
    else
      printf("%s\n", s);
    free(s);
  }

  if (got_membind) {
    if (hwloc_bitmap_iszero(membind_set)) {
      if (verbose >= 0)
	fprintf(stderr, "cannot membind to empty set\n");
      if (!force)
	goto failed_binding;
    }
    if (verbose > 0) {
      char *s;
      hwloc_bitmap_asprintf(&s, membind_set);
      fprintf(stderr, "binding on memory set %s\n", s);
      free(s);
    }
    if (single)
      hwloc_bitmap_singlify(membind_set);
    if (pid_number > 0)
      ret = hwloc_set_proc_membind(topology, pid, membind_set, membind_policy, membind_flags | HWLOC_MEMBIND_BYNODESET);
    else if (tid_number > 0) {
      ret = -1; errno = ENOSYS;
    } else
      ret = hwloc_set_membind(topology, membind_set, membind_policy, membind_flags | HWLOC_MEMBIND_BYNODESET);
    if (ret && verbose >= 0) {
      int bind_errno = errno;
      const char *errmsg = strerror(bind_errno);
      char *s;
      hwloc_bitmap_asprintf(&s, membind_set);
      if (pid_number > 0)
        fprintf(stderr, "hwloc_set_proc_membind %s (policy %d flags %x) PID %d failed (errno %d %s)\n",
		s, membind_policy, membind_flags, pid_number, bind_errno, errmsg);
      else
        fprintf(stderr, "hwloc_set_membind %s (policy %d flags %x) failed (errno %d %s)\n",
		s, membind_policy, membind_flags, bind_errno, errmsg);
      free(s);
    }
    if (ret && !force)
      goto failed_binding;
  } else {
    if (got_mempolicy)
      fprintf(stderr, "--mempolicy ignored unless memory binding is also requested with --membind.\n");
  }

  if (got_cpubind) {
    if (hwloc_bitmap_iszero(cpubind_set)) {
      if (verbose >= 0)
	fprintf(stderr, "cannot cpubind to empty set\n");
      if (!force)
	goto failed_binding;
    }
    if (verbose > 0) {
      char *s;
      hwloc_bitmap_asprintf(&s, cpubind_set);
      fprintf(stderr, "binding on cpu set %s\n", s);
      free(s);
    }
    if (got_membind && !hwloc_bitmap_isequal(membind_set, cpubind_set)) {
      if (verbose)
	fprintf(stderr, "Conflicting CPU and memory binding requested, adding HWLOC_CPUBIND_NOMEMBIND flag.\n");
      cpubind_flags |= HWLOC_CPUBIND_NOMEMBIND;
    }
    if (single)
      hwloc_bitmap_singlify(cpubind_set);
    if (pid_number > 0)
      ret = hwloc_set_proc_cpubind(topology, pid, cpubind_set, cpubind_flags);
#ifdef HWLOC_LINUX_SYS
    else if (tid_number > 0)
      ret = hwloc_linux_set_tid_cpubind(topology, tid_number, cpubind_set);
#endif
    else
      ret = hwloc_set_cpubind(topology, cpubind_set, cpubind_flags);
    if (ret && verbose >= 0) {
      int bind_errno = errno;
      const char *errmsg = strerror(bind_errno);
      char *s;
      hwloc_bitmap_asprintf(&s, cpubind_set);
      if (pid_number > 0)
        fprintf(stderr, "hwloc_set_proc_cpubind %s (flags %x) PID %d failed (errno %d %s)\n",
		s, cpubind_flags, pid_number, bind_errno, errmsg);
      else if (tid_number > 0)
        fprintf(stderr, "hwloc_set_tid_cpubind %s (flags %x) PID %d failed (errno %d %s)\n",
		s, cpubind_flags, tid_number, bind_errno, errmsg);
      else
        fprintf(stderr, "hwloc_set_cpubind %s (flags %x) failed (errno %d %s)\n",
		s, cpubind_flags, bind_errno, errmsg);
      free(s);
    }
    if (ret && !force)
      goto failed_binding;
  }

  hwloc_bitmap_free(cpubind_set);
  hwloc_bitmap_free(membind_set);

  hwloc_topology_destroy(topology);

  if (pid_number > 0 || tid_number > 0)
    return EXIT_SUCCESS;

  if (0 == argc) {
    if (get_binding || get_last_cpu_location)
      return EXIT_SUCCESS;
    fprintf(stderr, "%s: nothing to do!\n", callname);
    return EXIT_FAILURE;
  }

  /* FIXME: check whether Windows execvp() passes INHERIT_PARENT_AFFINITY to CreateProcess()
   * because we need to propagate processor group affinity. However process-wide affinity
   * isn't supported with processor groups so far.
   */
  ret = execvp(argv[0], argv);
  if (ret) {
      fprintf(stderr, "%s: Failed to launch executable \"%s\"\n",
              callname, argv[0]);
      perror("execvp");
  }
  return EXIT_FAILURE;


failed_binding:
  hwloc_bitmap_free(cpubind_set);
  hwloc_bitmap_free(membind_set);
  hwloc_topology_destroy(topology);
  return EXIT_FAILURE;
}