/* * Copyright © 2009 CNRS * Copyright © 2009-2011 INRIA. All rights reserved. * Copyright © 2009-2011 Université Bordeaux 1 * Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. */ #include #include #include #include "misc.h" #include #include #include void usage(const char *callname __hwloc_attribute_unused, FILE *where) { fprintf(where, "Usage: hwloc-calc [options] ...\n"); fprintf(where, " may be a space-separated list of cpusets or objects\n"); fprintf(where, " as supported by the hwloc-bind utility.\n"); fprintf(where, "Options:\n"); fprintf(where, " -l --logical Use logical object indexes (default)\n"); fprintf(where, " -p --physical Use physical object indexes\n"); fprintf(where, " --li --logical-input Use logical indexes for input (default)\n"); fprintf(where, " --lo --logical-output Use logical indexes for output (default)\n"); fprintf(where, " --pi --physical-input Use physical indexes for input\n"); fprintf(where, " --po --physical-output Use physical indexes for output\n"); fprintf(where, " --number-of \n" " -N Report the number of objects intersecting the CPU set\n"); fprintf(where, " --intersect \n" " -I Report the indexes of object intersecting the CPU set\n"); fprintf(where, " --hierarchical ....\n" " -H .... Find the list of objects intersecting the CPU set and\n" " display them as hierarchical combinations such as\n" " type1:index1.type2:index2...\n"); fprintf(where, " --largest Report the list of largest objects in the CPU set\n"); fprintf(where, " --single Singlify the output to a single CPU\n"); fprintf(where, " --taskset Manipulate taskset-specific cpuset strings\n"); hwloc_utils_input_format_usage(where, 10); fprintf(where, " -v Show verbose messages\n"); fprintf(where, " --version Report version and exit\n"); } static int verbose = 0; static int logicali = 1; static int logicalo = 1; static int numberofdepth = -1; static int intersectdepth = -1; static int hiernblevels = 0; static int *hierdepth = NULL; static int showobjs = 0; static int singlify = 0; static int taskset = 0; static void hwloc_calc_hierarch_output(hwloc_topology_t topology, const char *prefix, hwloc_bitmap_t set, int level) { hwloc_obj_t obj, prev = NULL; unsigned logi = 0; while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, hierdepth[level], prev)) != NULL) { char string[256]; char type[32]; hwloc_obj_type_snprintf(type, sizeof(type), obj, 1); snprintf(string, sizeof(string), "%s%s%s:%u", prefix, level ? "." : "", type, logicalo ? logi : obj->os_index); if (prev) printf(" "); if (level != hiernblevels - 1) { hwloc_bitmap_t new = hwloc_bitmap_dup(set); hwloc_bitmap_and(new, new, obj->cpuset); hwloc_calc_hierarch_output(topology, string, new, level+1); hwloc_bitmap_free(new); } else { printf("%s", string); } prev = obj; logi++; } } static int hwloc_calc_output(hwloc_topology_t topology, hwloc_bitmap_t set) { if (singlify) hwloc_bitmap_singlify(set); if (showobjs) { hwloc_bitmap_t remaining = hwloc_bitmap_dup(set); int first = 1; while (!hwloc_bitmap_iszero(remaining)) { char type[64]; unsigned idx; hwloc_obj_t obj = hwloc_get_first_largest_obj_inside_cpuset(topology, remaining); if (!obj) { fprintf(stderr, "No object included in this cpuset\n"); return EXIT_FAILURE; } hwloc_obj_type_snprintf(type, sizeof(type), obj, 1); idx = logicalo ? obj->logical_index : obj->os_index; if (idx == (unsigned) -1) printf("%s%s", first ? "" : " ", type); else printf("%s%s:%u", first ? "" : " ", type, idx); hwloc_bitmap_andnot(remaining, remaining, obj->cpuset); first = 0; } printf("\n"); hwloc_bitmap_free(remaining); } else if (numberofdepth != -1) { unsigned nb = 0; hwloc_obj_t obj = NULL; while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, numberofdepth, obj)) != NULL) nb++; printf("%u\n", nb); } else if (intersectdepth != -1) { hwloc_obj_t proc, prev = NULL; while ((proc = hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, intersectdepth, prev)) != NULL) { if (prev) printf(","); printf("%u", logicalo ? proc->logical_index : proc->os_index); prev = proc; } printf("\n"); } else if (hiernblevels) { hwloc_calc_hierarch_output(topology, "", set, 0); printf("\n"); } else { char *string = NULL; if (taskset) hwloc_bitmap_taskset_asprintf(&string, set); else hwloc_bitmap_asprintf(&string, set); printf("%s\n", string); free(string); } return EXIT_SUCCESS; } static int hwloc_calc_type_depth(const char *string, hwloc_obj_type_t *typep, int *depthp) { hwloc_obj_type_t type = hwloc_obj_type_of_string(string); int depth = -1; if (type == (hwloc_obj_type_t) -1) { char *endptr; depth = strtoul(string, &endptr, 0); if (*endptr) return -1; } *depthp = depth; *typep = type; return 0; } static int hwloc_calc_check_type_depth(hwloc_topology_t topology, hwloc_obj_type_t type, int *depthp, const char *caller) { if (type != (hwloc_obj_type_t) -1) { int depth = hwloc_get_type_depth(topology, type); if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { fprintf(stderr, "unavailable %s type %s\n", caller, hwloc_obj_type_string(type)); return -1; } else if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) { fprintf(stderr, "cannot use %s type %s with multiple depth, please use the relevant depth directly\n", caller, hwloc_obj_type_string(type)); return -1; } *depthp = depth; } return 0; } int main(int argc, char *argv[]) { hwloc_topology_t topology; char *input = NULL; enum hwloc_utils_input_format input_format = HWLOC_UTILS_INPUT_DEFAULT; int input_changed = 0; unsigned depth; hwloc_bitmap_t set; int cmdline_args = 0; char **orig_argv = argv; hwloc_obj_type_t numberoftype = (hwloc_obj_type_t) -1; hwloc_obj_type_t intersecttype = (hwloc_obj_type_t) -1; hwloc_obj_type_t *hiertype = NULL; char *callname; int opt; int i; int err; int ret = EXIT_SUCCESS; callname = argv[0]; set = hwloc_bitmap_alloc(); hwloc_topology_init(&topology); hwloc_topology_load(topology); depth = hwloc_topology_get_depth(topology); while (argc >= 2) { if (*argv[1] == '-') { if (!strcmp(argv[1], "-v")) { verbose = 1; goto next; } if (!strcmp(argv[1], "--help")) { usage(callname, stdout); return EXIT_SUCCESS; } if (!strcmp(argv[1], "--number-of") || !strcmp(argv[1], "-N")) { if (argc <= 2) { usage(callname, stderr); return EXIT_SUCCESS; } if (hwloc_calc_type_depth(argv[2], &numberoftype, &numberofdepth) < 0) { fprintf(stderr, "unrecognized --number-of type or depth %s\n", argv[2]); usage(callname, stderr); return EXIT_SUCCESS; } argv++; argc--; goto next; } if (!strcmp(argv[1], "--intersect") || !strcmp(argv[1], "-I")) { if (argc <= 2) { usage(callname, stderr); return EXIT_SUCCESS; } if (hwloc_calc_type_depth(argv[2], &intersecttype, &intersectdepth) < 0) { fprintf(stderr, "unrecognized --intersect type or depth %s\n", argv[2]); usage(callname, stderr); return EXIT_SUCCESS; } argv++; argc--; goto next; } if (!strcmp(argv[1], "--hierarchical") || !strcmp(argv[1], "-H")) { char *tmp, *next; if (argc <= 2) { usage(callname, stderr); return EXIT_SUCCESS; } hiernblevels = 1; tmp = argv[2]; while (1) { tmp = strchr(tmp, '.'); if (!tmp) break; tmp++; hiernblevels++; } hiertype = malloc(hiernblevels * sizeof(hwloc_obj_type_t)); hierdepth = malloc(hiernblevels * sizeof(int)); tmp = argv[2]; for(i=0; i