Skip to content

Commit 6095a74

Browse files
committed
API: add hwloc_modify_infos() to add/replace/remove info attrs
hwloc_obj_add_info() is now implemented on top of it. Signed-off-by: Brice Goglin <[email protected]>
1 parent 293206f commit 6095a74

File tree

7 files changed

+181
-11
lines changed

7 files changed

+181
-11
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Version 3.0.0
3636
root object together with other backends.
3737
+ The array and count of info attributes are now embedded in the new
3838
struct hwloc_infos_s.
39+
- hwloc_infos_s structures may be modified with hwloc_modify_infos().
3940
- hwloc_cpukinds_get_info() and hwloc_cpukinds_register() now manipulate
4041
infos as such a structure.
4142
* Tools

doc/Makefile.am

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,13 @@ man3_object_info_attrs_DATA = \
350350
$(DOX_MAN_DIR)/man3/hwlocality_info_attr.3 \
351351
$(DOX_MAN_DIR)/man3/hwloc_obj_get_info_by_name.3 \
352352
$(DOX_MAN_DIR)/man3/hwloc_get_info_by_name.3 \
353-
$(DOX_MAN_DIR)/man3/hwloc_obj_add_info.3
353+
$(DOX_MAN_DIR)/man3/hwloc_obj_add_info.3 \
354+
$(DOX_MAN_DIR)/man3/hwloc_modify_infos.3 \
355+
$(DOX_MAN_DIR)/man3/hwloc_modify_infos_op_e.3 \
356+
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_ADD.3 \
357+
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_ADD_UNIQUE.3 \
358+
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_REPLACE.3 \
359+
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_REMOVE.3
354360

355361
man3_cpubindingdir = $(man3dir)
356362
man3_cpubinding_DATA = \

doc/hwloc.doxy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,7 +1970,7 @@ Each object contains a list of such pairs that may be consulted
19701970
manually (looking at the object <tt>infos</tt> array field)
19711971
or using the hwloc_obj_get_info_by_name().
19721972
The user may additionally add new name-value pairs to any object using
1973-
hwloc_obj_add_info() or the \ref cli_hwloc_annotate program.
1973+
hwloc_obj_add_info(), hwloc_modify_infos() or the \ref cli_hwloc_annotate program.
19741974

19751975
Here is a non-exhaustive list of attributes that may be automatically
19761976
added by hwloc.
@@ -3970,7 +3970,7 @@ and <tt>hwloc_topology_set_userdata_import_callback()</tt>.
39703970
Each object may also contain some <em>info</em> attributes
39713971
(name and value strings) that are setup by hwloc during discovery
39723972
and that may be extended by the user with
3973-
<tt>hwloc_obj_add_info()</tt> (see also \ref attributes).
3973+
<tt>hwloc_obj_add_info()</tt> or <tt>hwloc_modify_infos()</tt> (see also \ref attributes).
39743974
Contrary to the <tt>userdata</tt> field which is unique, multiple info
39753975
attributes may exist for each object, even with the same name.
39763976
These attributes are always exported to XML.

hwloc/topology.c

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,23 @@ int hwloc__add_info(struct hwloc_infos_s *infos, const char *name, const char *v
523523
return -1;
524524
}
525525

526+
static int hwloc__add_info_unique(struct hwloc_infos_s *infos, const char *name, const char *value)
527+
{
528+
struct hwloc_info_s *array = infos->array;
529+
unsigned i, count = infos->count;
530+
531+
if (!name || !value) {
532+
errno = EINVAL;
533+
return -1;
534+
}
535+
536+
for(i=0; i<count; i++)
537+
if (!strcmp(array[i].name, name) && !strcmp(array[i].value, value))
538+
return 0;
539+
540+
return hwloc__add_info(infos, name, value);
541+
}
542+
526543
int hwloc__add_info_nodup(struct hwloc_infos_s *infos,
527544
const char *name, const char *value,
528545
int replace)
@@ -551,6 +568,92 @@ int hwloc__add_info_nodup(struct hwloc_infos_s *infos,
551568
return hwloc__add_info(infos, name, value);
552569
}
553570

571+
static int hwloc__replace_infos(struct hwloc_infos_s *infos,
572+
const char *name, const char *value)
573+
{
574+
struct hwloc_info_s *array = infos->array;
575+
unsigned count = infos->count;
576+
unsigned i;
577+
int found = 0;
578+
579+
if (!name || !value) {
580+
errno = EINVAL;
581+
return -1;
582+
}
583+
584+
for(i=0; i<count; i++) {
585+
if (!strcmp(array[i].name, name)) {
586+
if (!found) {
587+
/* first match, replace */
588+
char *new = strdup(value);
589+
if (!new)
590+
return -1;
591+
free(array[i].value);
592+
array[i].value = new;
593+
} else {
594+
/* non-first match, remove */
595+
free(array[i].name);
596+
free(array[i].value);
597+
}
598+
found++;
599+
} else if (found > 1) {
600+
/* non-match, move left by found-1 */
601+
array[i-(found-1)].name = array[i].name;
602+
array[i-(found-1)].value = array[i].value;
603+
}
604+
}
605+
if (found) {
606+
if (found > 1)
607+
infos->count -= found-1;
608+
return 0;
609+
} else {
610+
/* no match, just add */
611+
return hwloc__add_info(infos, name, value);
612+
}
613+
}
614+
615+
static int hwloc__remove_infos(struct hwloc_infos_s *infos,
616+
const char *name, const char *value)
617+
{
618+
struct hwloc_info_s *array = infos->array;
619+
unsigned count = infos->count;
620+
unsigned i;
621+
int found = 0;
622+
623+
for(i=0; i<count; i++) {
624+
if ((!name || !strcmp(array[i].name, name))
625+
&& (!value || !strcmp(array[i].value, value))) {
626+
/* match, remove */
627+
free(array[i].name);
628+
free(array[i].value);
629+
found++;
630+
} else {
631+
/* non-match, move left by found */
632+
array[i-found].name = array[i].name;
633+
array[i-found].value = array[i].value;
634+
}
635+
}
636+
infos->count -= found;
637+
return 0;
638+
}
639+
640+
int hwloc_modify_infos(struct hwloc_infos_s *infos, unsigned long op, const char *name, const char *value)
641+
{
642+
switch (op) {
643+
case HWLOC_MODIFY_INFOS_OP_ADD:
644+
return hwloc__add_info(infos, name, value);
645+
case HWLOC_MODIFY_INFOS_OP_ADD_UNIQUE:
646+
return hwloc__add_info_unique(infos, name, value);
647+
case HWLOC_MODIFY_INFOS_OP_REPLACE:
648+
return hwloc__replace_infos(infos, name, value);
649+
case HWLOC_MODIFY_INFOS_OP_REMOVE:
650+
return hwloc__remove_infos(infos, name, value);
651+
default:
652+
errno = EINVAL;
653+
return -1;
654+
}
655+
}
656+
554657
int hwloc__move_infos(struct hwloc_infos_s *dst_infos,
555658
struct hwloc_infos_s *src_infos)
556659
{
@@ -591,11 +694,6 @@ int hwloc__move_infos(struct hwloc_infos_s *dst_infos,
591694
return -1;
592695
}
593696

594-
int hwloc_obj_add_info(hwloc_obj_t obj, const char *name, const char *value)
595-
{
596-
return hwloc__add_info(&obj->infos, name, value);
597-
}
598-
599697
/* This function may be called with topology->tma set, it cannot free() or realloc() */
600698
int hwloc__tma_dup_infos(struct hwloc_tma *tma,
601699
struct hwloc_infos_s *newi,

include/hwloc.h

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,8 @@ struct hwloc_info_s {
426426

427427
/** \brief Array of string info attributes (pairs of name and value).
428428
*
429-
* These structures may only be modified with hwloc_obj_add_info().
429+
* These structures may only be modified with hwloc_obj_add_info()
430+
* and hwloc_modify_infos().
430431
*
431432
* \sa hwlocality_info_attr
432433
*/
@@ -1155,10 +1156,61 @@ hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name) __hwloc_attribute_
11551156
static __hwloc_inline const char *
11561157
hwloc_get_info_by_name(struct hwloc_infos_s *infos, const char *name) __hwloc_attribute_pure;
11571158

1159+
/** \brief Modify an array of info attributes.
1160+
*
1161+
* \p operation is a single value among enum hwloc_modify_infos_op_e.
1162+
*
1163+
* If adding (::HWLOC_MODIFY_INFOS_OP_ADD or ::HWLOC_MODIFY_INFOS_OP_ADD_UNIQUE)
1164+
* or replacing (::HWLOC_MODIFY_INFOS_OP_REPLACE) an info attribute,
1165+
* \p name and \p value cannot be \c NULL.
1166+
* The input strings are copied before being added in the object infos.
1167+
*
1168+
* If removing existing info pairs (::HWLOC_MODIFY_INFOS_OP_REMOVE),
1169+
* \p name and/or \p value may be non \c NULL to specify which pair(s) to remove.
1170+
* If both \p name and \p value are \c NULL, all pairs are removed.
1171+
*
1172+
* \return \c 0 on success, \c -1 on error.
1173+
*
1174+
* \note If \p value contains some non-printable characters, they will
1175+
* be dropped when exporting to XML, see hwloc_topology_export_xml() in hwloc/export.h.
1176+
*/
1177+
HWLOC_DECLSPEC int hwloc_modify_infos(struct hwloc_infos_s *infos,
1178+
unsigned long operation,
1179+
const char *name, const char *value);
1180+
1181+
/** \brief Operations given to hwloc_modify_infos(). */
1182+
enum hwloc_modify_infos_op_e {
1183+
/** \brief Add a new info attribute with the given name and value.
1184+
* \hideinitializer
1185+
*/
1186+
HWLOC_MODIFY_INFOS_OP_ADD = 1UL<<0,
1187+
1188+
/** \brief Add a new info attribute with the given name and value
1189+
* only if that pair doesn't exist yet.
1190+
* \hideinitializer
1191+
*/
1192+
HWLOC_MODIFY_INFOS_OP_ADD_UNIQUE = 1UL<<1,
1193+
1194+
/** \brief Replace existing info attributes with the given name,
1195+
* with a single attribute with the given name and value.
1196+
* If no existing pair matches, add a new one.
1197+
* If multiple pairs match, only one remains.
1198+
* \hideinitializer
1199+
*/
1200+
HWLOC_MODIFY_INFOS_OP_REPLACE = 1UL<<2,
1201+
1202+
/** \brief Remove existing info attributes that matches the given
1203+
* name and/or value if not \c NULL.
1204+
* \hideinitializer
1205+
*/
1206+
HWLOC_MODIFY_INFOS_OP_REMOVE = 1UL<<3
1207+
};
1208+
11581209
/** \brief Add the given name and value pair to the given object info attributes.
11591210
*
11601211
* The info pair is appended to the existing info array even if another pair
1161-
* with the same name already exists.
1212+
* with the same name already exists. See hwloc_modify_infos() for a more
1213+
* flexible variant.
11621214
*
11631215
* The input strings are copied before being added in the object infos.
11641216
*
@@ -1173,7 +1225,8 @@ hwloc_get_info_by_name(struct hwloc_infos_s *infos, const char *name) __hwloc_at
11731225
* \note If \p name or \p value contain some non-printable characters, they will
11741226
* be dropped when exporting to XML, see hwloc_topology_export_xml() in hwloc/export.h.
11751227
*/
1176-
HWLOC_DECLSPEC int hwloc_obj_add_info(hwloc_obj_t obj, const char *name, const char *value);
1228+
static __hwloc_inline int
1229+
hwloc_obj_add_info(hwloc_obj_t obj, const char *name, const char *value);
11771230

11781231
/** @} */
11791232

include/hwloc/inlines.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name)
125125
return hwloc_get_info_by_name(&obj->infos, name);
126126
}
127127

128+
static __hwloc_inline int
129+
hwloc_obj_add_info(hwloc_obj_t obj, const char *name, const char *value)
130+
{
131+
return hwloc_modify_infos(&obj->infos, HWLOC_MODIFY_INFOS_OP_ADD, name, value);
132+
}
133+
128134
static __hwloc_inline void *
129135
hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags)
130136
{

include/hwloc/rename.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ extern "C" {
218218
#define hwloc_obj_get_info_by_name HWLOC_NAME(obj_get_info_by_name)
219219
#define hwloc_get_info_by_name HWLOC_NAME(get_info_by_name)
220220
#define hwloc_obj_add_info HWLOC_NAME(obj_add_info)
221+
#define hwloc_modify_infos HWLOC_NAME(modify_infos)
222+
#define hwloc_modify_infos_op_e HWLOC_NAME(modify_infos_op_e)
223+
#define HWLOC_MODIFY_INFOS_OP_ADD HWLOC_NAME_CAPS(MODIFY_INFOS_OP_ADD)
224+
#define HWLOC_MODIFY_INFOS_OP_ADD_UNIQUE HWLOC_NAME_CAPS(MODIFY_INFOS_OP_ADD_UNIQUE)
225+
#define HWLOC_MODIFY_INFOS_OP_REPLACE HWLOC_NAME_CAPS(MODIFY_INFOS_OP_REPLACE)
226+
#define HWLOC_MODIFY_INFOS_OP_REMOVE HWLOC_NAME_CAPS(MODIFY_INFOS_OP_REMOVE)
221227

222228
#define HWLOC_CPUBIND_PROCESS HWLOC_NAME_CAPS(CPUBIND_PROCESS)
223229
#define HWLOC_CPUBIND_THREAD HWLOC_NAME_CAPS(CPUBIND_THREAD)

0 commit comments

Comments
 (0)