From 74f1b795ffe6879c7b083c83ba639e51263ec739 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Mon, 3 Feb 2014 20:21:59 +0100 Subject: [PATCH] Add hwloc_obj_type_sscanf() to extend hwloc_obj_type_of_string() The former was already used in hwloc-calc.h to parse things like "L2iCache" or "Group3". Make it officially part of the API and deprecate the old hwloc_obj_type_of_string(). --- NEWS | 3 ++ doc/Makefile.am | 2 +- include/hwloc.h | 33 ++++++++++++++-- include/hwloc/deprecated.h | 8 +++- include/hwloc/rename.h | 5 ++- src/topology-xml.c | 5 +-- src/traversal.c | 70 +++++++++++++++++++++++++++++++++- utils/hwloc-calc.c | 6 +-- utils/hwloc-calc.h | 77 +------------------------------------- utils/hwloc-distrib.c | 19 +++++----- utils/hwloc-info.c | 2 +- utils/lstopo.c | 15 +++----- 12 files changed, 135 insertions(+), 110 deletions(-) diff --git a/NEWS b/NEWS index 2ff1fb54..93ceb9af 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,9 @@ in v0.9.1). Version 1.9.0 ------------- * API + + Add hwloc_obj_type_sscanf() to extend hwloc_obj_type_of_string() with + type-specific attributes such as Cache/Group depth and Cache type. + hwloc_obj_type_of_string() is moved to hwloc/deprecated.h. + Add hwloc_linux_get_tid_last_cpu_location() for retrieving the last CPU where a Linux thread given by TID ran. * Backends diff --git a/doc/Makefile.am b/doc/Makefile.am index 037d1722..b19de94e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -385,7 +385,7 @@ man3_object_stringsdir = $(man3dir) man3_object_strings_DATA = \ $(DOX_MAN_DIR)/man3/hwlocality_object_strings.3 \ $(DOX_MAN_DIR)/man3/hwloc_obj_type_string.3 \ - $(DOX_MAN_DIR)/man3/hwloc_obj_type_of_string.3 \ + $(DOX_MAN_DIR)/man3/hwloc_obj_type_sscanf.3 \ $(DOX_MAN_DIR)/man3/hwloc_obj_type_snprintf.3 \ $(DOX_MAN_DIR)/man3/hwloc_obj_attr_snprintf.3 \ $(DOX_MAN_DIR)/man3/hwloc_obj_cpuset_snprintf.3 \ diff --git a/include/hwloc.h b/include/hwloc.h index 83bdbe4e..ca086ffd 100644 --- a/include/hwloc.h +++ b/include/hwloc.h @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2012 Université Bordeaux 1 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -1173,11 +1173,36 @@ hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, /** \brief Return a stringified topology object type */ HWLOC_DECLSPEC const char * hwloc_obj_type_string (hwloc_obj_type_t type) __hwloc_attribute_const; -/** \brief Return an object type from the string +/** \brief Return an object type and attributes from a type string. * - * \return -1 if unrecognized. + * Convert strings such as "socket" or "cache" into the corresponding types. + * Matching is case-insensitive, and only the first letters are actually + * required to match. + * + * Types that have specific attributes, for instance caches and groups, + * may be returned in \p depthattrp and \p typeattrp. They are ignored + * when these pointers are \c NULL. + * + * For instance "L2i" or "L2iCache" would return + * type HWLOC_OBJ_CACHE in \p typep, 2 in \p depthattrp, + * and HWLOC_OBJ_CACHE_TYPE_INSTRUCTION in \p typeattrp + * (this last pointer should point to a hwloc_obj_cache_type_t). + * "Group3" would return type HWLOC_OBJ_GROUP type and 3 in \p depthattrp. + * Attributes that are not specified in the string (for instance "Group" + * without a depth, or "L2Cache" without a cache type) are set to -1. + * + * \p typeattrd is only filled if the size specified in \p typeattrsize + * is large enough. It is currently only used for caches, and the required + * size is at least the size of hwloc_obj_cache_type_t. + * + * \return 0 if a type was correctly identified, otherwise -1. + * + * \note This is an extended version of the now deprecated hwloc_obj_type_of_string() */ -HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure; +HWLOC_DECLSPEC int hwloc_obj_type_sscanf(const char *string, + hwloc_obj_type_t *typep, + int *depthattrp, + void *typeattrp, size_t typeattrsize); /** \brief Stringify the type of a given topology object into a human-readable form. * diff --git a/include/hwloc/deprecated.h b/include/hwloc/deprecated.h index 544ca8f0..5b1f671f 100644 --- a/include/hwloc/deprecated.h +++ b/include/hwloc/deprecated.h @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2012 Université Bordeaux 1 * Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -21,6 +21,12 @@ extern "C" { #endif +/** \brief Return an object type from the string + * + * \return -1 if unrecognized. + */ +HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure; + /** \brief Stringify a given topology object into a human-readable form. * * \note This function is deprecated in favor of hwloc_obj_type_snprintf() diff --git a/include/hwloc/rename.h b/include/hwloc/rename.h index b7dd666b..cdce0b24 100644 --- a/include/hwloc/rename.h +++ b/include/hwloc/rename.h @@ -1,6 +1,6 @@ /* * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. - * Copyright © 2010-2013 Inria. All rights reserved. + * Copyright © 2010-2014 Inria. All rights reserved. * See COPYING in top-level directory. */ @@ -176,7 +176,7 @@ extern "C" { #define hwloc_get_obj_by_type HWLOC_NAME(get_obj_by_type ) #define hwloc_obj_type_string HWLOC_NAME(obj_type_string ) -#define hwloc_obj_type_of_string HWLOC_NAME(obj_type_of_string ) +#define hwloc_obj_type_sscanf HWLOC_NAME(obj_type_sscanf) #define hwloc_obj_type_snprintf HWLOC_NAME(obj_type_snprintf ) #define hwloc_obj_attr_snprintf HWLOC_NAME(obj_attr_snprintf ) #define hwloc_obj_cpuset_snprintf HWLOC_NAME(obj_cpuset_snprintf) @@ -493,6 +493,7 @@ extern "C" { /* hwloc/deprecated.h */ +#define hwloc_obj_type_of_string HWLOC_NAME(obj_type_of_string ) #define hwloc_obj_snprintf HWLOC_NAME(obj_snprintf) /* private/debug.h */ diff --git a/src/topology-xml.c b/src/topology-xml.c index fd5d7e40..cf1d3a1a 100644 --- a/src/topology-xml.c +++ b/src/topology-xml.c @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2011 Université Bordeaux 1 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -559,8 +559,7 @@ hwloc__xml_import_object(hwloc_topology_t topology, if (state->next_attr(state, &attrname, &attrvalue) < 0) break; if (!strcmp(attrname, "type")) { - obj->type = hwloc_obj_type_of_string(attrvalue); - if (obj->type == (hwloc_obj_type_t)-1) + if (hwloc_obj_type_sscanf(attrvalue, &obj->type, NULL, NULL, 0) < 0) return -1; } else { /* type needed first */ diff --git a/src/traversal.c b/src/traversal.c index 6e678342..91b0c226 100644 --- a/src/traversal.c +++ b/src/traversal.c @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2012 inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2010 Université Bordeaux 1 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -213,6 +213,74 @@ hwloc_obj_type_of_string (const char * string) return (hwloc_obj_type_t) -1; } +int +hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize) +{ + hwloc_obj_type_t type = (hwloc_obj_type_t) -1; + int depthattr = -1; + hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */ + char *end; + + /* types without depthattr */ + if (!hwloc_strncasecmp(string, "system", 2)) { + type = HWLOC_OBJ_SYSTEM; + } else if (!hwloc_strncasecmp(string, "machine", 2)) { + type = HWLOC_OBJ_MACHINE; + } else if (!hwloc_strncasecmp(string, "node", 1) + || !hwloc_strncasecmp(string, "numa", 1)) { /* matches node and numanode */ + type = HWLOC_OBJ_NODE; + } else if (!hwloc_strncasecmp(string, "socket", 2)) { + type = HWLOC_OBJ_SOCKET; + } else if (!hwloc_strncasecmp(string, "core", 2)) { + type = HWLOC_OBJ_CORE; + } else if (!hwloc_strncasecmp(string, "pu", 2)) { + type = HWLOC_OBJ_PU; + } else if (!hwloc_strncasecmp(string, "misc", 2)) { + type = HWLOC_OBJ_MISC; + } else if (!hwloc_strncasecmp(string, "bridge", 2)) { + type = HWLOC_OBJ_BRIDGE; + } else if (!hwloc_strncasecmp(string, "pci", 2)) { + type = HWLOC_OBJ_PCI_DEVICE; + } else if (!hwloc_strncasecmp(string, "os", 2)) { + type = HWLOC_OBJ_OS_DEVICE; + + /* types with depthattr */ + } else if (!hwloc_strncasecmp(string, "cache", 2)) { + type = HWLOC_OBJ_CACHE; + + } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') { + type = HWLOC_OBJ_CACHE; + depthattr = strtol(string+1, &end, 10); + if (*end == 'd') { + cachetypeattr = HWLOC_OBJ_CACHE_DATA; + } else if (*end == 'i') { + cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION; + } else if (*end == 'u') { + cachetypeattr = HWLOC_OBJ_CACHE_UNIFIED; + } + + } else if (!hwloc_strncasecmp(string, "group", 2)) { + int length; + type = HWLOC_OBJ_GROUP; + length = strcspn(string, "0123456789"); + if (length <= 5 && !hwloc_strncasecmp(string, "group", length) + && string[length] >= '0' && string[length] <= '9') { + depthattr = strtol(string+length, &end, 10); + } + } else + return -1; + + *typep = type; + if (depthattrp) + *depthattrp = depthattr; + if (typeattrp) { + if (type == HWLOC_OBJ_CACHE && sizeof(hwloc_obj_cache_type_t) <= typeattrsize) + memcpy(typeattrp, &cachetypeattr, sizeof(hwloc_obj_cache_type_t)); + } + + return 0; +} + static const char * hwloc_pci_class_string(unsigned short class_id) { diff --git a/utils/hwloc-calc.c b/utils/hwloc-calc.c index 0d91a27a..bcd4b9b9 100644 --- a/utils/hwloc-calc.c +++ b/utils/hwloc-calc.c @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 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. @@ -161,9 +161,9 @@ hwloc_calc_output(hwloc_topology_t topology, const char *sep, hwloc_bitmap_t set 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); + hwloc_obj_type_t type = (hwloc_obj_type_t) -1; /* in case we match a depth */ int depth = -1; - if (type == (hwloc_obj_type_t) -1) { + if (hwloc_obj_type_sscanf(string, &type, NULL, NULL, 0) < 0) { char *endptr; depth = strtoul(string, &endptr, 0); if (*endptr) diff --git a/utils/hwloc-calc.h b/utils/hwloc-calc.h index 5a1dfc54..a1e7d36e 100644 --- a/utils/hwloc-calc.h +++ b/utils/hwloc-calc.h @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2012 Université Bordeaux 1 * Copyright © 2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -85,79 +85,6 @@ hwloc_calc_get_obj_inside_cpuset_by_depth(hwloc_topology_t topology, hwloc_const } } -/* extended version of hwloc_obj_type_of_string() - * - * matches L2, L3Cache and Group4, and return the corresponding depth attribute if depthattrp isn't NULL. - * only looks at the beginning of the string to allow truncated type names. - */ -static __hwloc_inline int -hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, hwloc_obj_cache_type_t *cachetypeattrp) -{ - hwloc_obj_type_t type = (hwloc_obj_type_t) -1; - int depthattr = -1; - hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */ - char *end; - - /* types without depthattr */ - if (!hwloc_strncasecmp(string, "system", 2)) { - type = HWLOC_OBJ_SYSTEM; - } else if (!hwloc_strncasecmp(string, "machine", 2)) { - type = HWLOC_OBJ_MACHINE; - } else if (!hwloc_strncasecmp(string, "node", 1)) { - type = HWLOC_OBJ_NODE; - } else if (!hwloc_strncasecmp(string, "socket", 2)) { - type = HWLOC_OBJ_SOCKET; - } else if (!hwloc_strncasecmp(string, "core", 2)) { - type = HWLOC_OBJ_CORE; - } else if (!hwloc_strncasecmp(string, "pu", 2)) { - type = HWLOC_OBJ_PU; - } else if (!hwloc_strncasecmp(string, "misc", 2)) { - type = HWLOC_OBJ_MISC; - } else if (!hwloc_strncasecmp(string, "pci", 2)) { - type = HWLOC_OBJ_PCI_DEVICE; - } else if (!hwloc_strncasecmp(string, "os", 2)) { - type = HWLOC_OBJ_OS_DEVICE; - - /* types with depthattr */ - } else if (!hwloc_strncasecmp(string, "cache", 2)) { - type = HWLOC_OBJ_CACHE; - } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') { - type = HWLOC_OBJ_CACHE; - depthattr = strtol(string+1, &end, 10); - if (*end == 'd') { - cachetypeattr = HWLOC_OBJ_CACHE_DATA; - end++; - } else if (*end == 'i') { - cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION; - end++; - } else if (*end == 'u') { - cachetypeattr = HWLOC_OBJ_CACHE_UNIFIED; - end++; - } - if (*end && hwloc_strncasecmp(end, "cache", 2)) - return -1; - - } else if (!hwloc_strncasecmp(string, "group", 1)) { - int length; - type = HWLOC_OBJ_GROUP; - length = strcspn(string, "0123456789"); - if (string[length] != '\0') { - depthattr = strtol(string+length, &end, 10); - if (*end) - return -1; - } - } else - return -1; - - *typep = type; - if (depthattrp) - *depthattrp = depthattr; - if (cachetypeattrp) - *cachetypeattrp = cachetypeattr; - - return 0; -} - static __hwloc_inline int hwloc_calc_depth_of_type(hwloc_topology_t topology, hwloc_obj_type_t type, int depthattr, hwloc_obj_cache_type_t cachetype /* -1 if not specified */, @@ -242,7 +169,7 @@ hwloc_calc_parse_depth_prefix(hwloc_topology_t topology, unsigned topodepth, typestring[typelen] = '\0'; /* try to match a type name */ - err = hwloc_obj_type_sscanf(typestring, &type, &depthattr, &cachetypeattr); + err = hwloc_obj_type_sscanf(typestring, &type, &depthattr, &cachetypeattr, sizeof(cachetypeattr)); if (!err) { *typep = type; return hwloc_calc_depth_of_type(topology, type, depthattr, cachetypeattr, verbose); diff --git a/utils/hwloc-distrib.c b/utils/hwloc-distrib.c index b04c15be..a1145a15 100644 --- a/utils/hwloc-distrib.c +++ b/utils/hwloc-distrib.c @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2010 Université Bordeaux 1 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -103,11 +103,10 @@ int main(int argc, char *argv[]) usage(callname, stdout); exit(EXIT_FAILURE); } - type = hwloc_obj_type_of_string(argv[1]); - if (type != (hwloc_obj_type_t) -1) - hwloc_topology_ignore_type(topology, type); - else + if (hwloc_obj_type_sscanf(argv[1], &type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --ignore, ignoring.\n", argv[1]); + else + hwloc_topology_ignore_type(topology, type); argc--; argv++; goto next; @@ -117,8 +116,7 @@ int main(int argc, char *argv[]) usage(callname, stdout); exit(EXIT_FAILURE); } - from_type = hwloc_obj_type_of_string(argv[1]); - if (from_type == (hwloc_obj_type_t) -1) + if (hwloc_obj_type_sscanf(argv[1], &from_type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --from, ignoring.\n", argv[1]); argc--; argv++; @@ -129,8 +127,7 @@ int main(int argc, char *argv[]) usage(callname, stdout); exit(EXIT_FAILURE); } - to_type = hwloc_obj_type_of_string(argv[1]); - if (to_type == (hwloc_obj_type_t) -1) + if (hwloc_obj_type_sscanf(argv[1], &to_type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --to, ignoring.\n", argv[1]); argc--; argv++; @@ -141,7 +138,9 @@ int main(int argc, char *argv[]) usage(callname, stdout); exit(EXIT_FAILURE); } - from_type = to_type = hwloc_obj_type_of_string(argv[1]); + if (hwloc_obj_type_sscanf(argv[1], &to_type, NULL, NULL, 0) < 0) + fprintf(stderr, "Unsupported type `%s' passed to --at, ignoring.\n", argv[1]); + from_type = to_type; argc--; argv++; goto next; diff --git a/utils/hwloc-info.c b/utils/hwloc-info.c index 96e225a7..1d422395 100644 --- a/utils/hwloc-info.c +++ b/utils/hwloc-info.c @@ -303,7 +303,7 @@ main (int argc, char *argv[]) usage (callname, stderr); exit(EXIT_FAILURE); } - err = hwloc_obj_type_sscanf(argv[1], &show_ancestor_type, &show_ancestor_attrdepth, &show_ancestor_attrcachetype); + err = hwloc_obj_type_sscanf(argv[1], &show_ancestor_type, &show_ancestor_attrdepth, &show_ancestor_attrcachetype, sizeof(show_ancestor_attrcachetype)); if (err < 0) { fprintf(stderr, "unrecognized --ancestor type %s\n", argv[1]); usage(callname, stderr); diff --git a/utils/lstopo.c b/utils/lstopo.c index 7956289d..d9d146d8 100644 --- a/utils/lstopo.c +++ b/utils/lstopo.c @@ -1,6 +1,6 @@ /* * Copyright © 2009 CNRS - * Copyright © 2009-2013 Inria. All rights reserved. + * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2012 Université Bordeaux 1 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -405,8 +405,7 @@ main (int argc, char *argv[]) usage (callname, stderr); exit(EXIT_FAILURE); } - lstopo_show_only = hwloc_obj_type_of_string(argv[1]); - if (lstopo_show_only == (hwloc_obj_type_t) -1) + if (hwloc_obj_type_sscanf(argv[1], &lstopo_show_only, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --only, ignoring.\n", argv[1]); opt = 1; } @@ -416,8 +415,7 @@ main (int argc, char *argv[]) usage (callname, stderr); exit(EXIT_FAILURE); } - type = hwloc_obj_type_of_string(argv[1]); - if (type == (hwloc_obj_type_t) -1) + if (hwloc_obj_type_sscanf(argv[1], &type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --ignore, ignoring.\n", argv[1]); else if (type == HWLOC_OBJ_PU) lstopo_ignore_pus = 1; @@ -467,11 +465,10 @@ main (int argc, char *argv[]) hwloc_obj_type_t type; if (end) *end = '\0'; - type = hwloc_obj_type_of_string(tmp); - if (type != (hwloc_obj_type_t) -1) - force_orient[type] = orient; - else + if (hwloc_obj_type_sscanf(tmp, &type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to %s, ignoring.\n", tmp, argv[0]); + else + force_orient[type] = orient; if (!end) break; tmp = end+1; -- 2.39.5