Skip to content

Commit 2881434

Browse files
Checkpoint hardware pool work. (#86)
* Also fix an off-by-one error in qvi_hwloc_bitmap_nbits(). * Checkpoint some work looking into a potentially nicer way to deal with C++ objects. Signed-off-by: Samuel K. Gutierrez <[email protected]>
1 parent 2550431 commit 2881434

File tree

3 files changed

+124
-43
lines changed

3 files changed

+124
-43
lines changed

src/qvi-hwloc.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* -*- Mode: C++; c-basic-offset:4; indent-tabs-mode:nil -*- */
22
/*
3-
* Copyright (c) 2020-2023 Triad National Security, LLC
3+
* Copyright (c) 2020-2024 Triad National Security, LLC
44
* All rights reserved.
55
*
66
* Copyright (c) 2020-2021 Lawrence Livermore National Security, LLC
@@ -804,7 +804,7 @@ qvi_hwloc_bitmap_nbits(
804804
const int inbits = hwloc_bitmap_last(cpuset);
805805
if (inbits == -1) return QV_ERR_HWLOC;
806806

807-
*nbits = (size_t)inbits;
807+
*nbits = size_t(inbits) + 1;
808808
return QV_SUCCESS;
809809
}
810810

src/qvi-hwpool.cc

+88-40
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* -*- Mode: C++; c-basic-offset:4; indent-tabs-mode:nil -*- */
22
/*
3-
* Copyright (c) 2022 Triad National Security, LLC
3+
* Copyright (c) 2022-2024 Triad National Security, LLC
44
* All rights reserved.
55
*
66
* This file is part of the quo-vadis project. See the LICENSE file at the
@@ -48,39 +48,90 @@
4848
#include "qvi-hwloc.h"
4949
#include "qvi-utils.h"
5050

51-
struct qvi_hwpool_s {
52-
/** The cpuset of this resource pool. */
51+
/**
52+
* Maintains a mapping between a resource ID and associated hint flags.
53+
*/
54+
using qvi_hwpool_resource_id_hint_map_t = std::unordered_map<
55+
uint32_t, qv_scope_create_hint_t
56+
>;
57+
58+
/**
59+
* Maintains information about a pool of hardware resources by resource ID.
60+
*/
61+
struct qvi_hwpool_resource_info_s {
62+
/**
63+
* Vector maintaining the reference count for a given resource ID. There is
64+
* a one-to-one correspondence between resource IDs and addressable vector
65+
* slots since every resource is reference counted. For example, each bit in
66+
* a cpuset will have a corresponding reference count indexed by the bit's
67+
* location in the cpuset.
68+
*/
69+
std::vector<uint32_t> resid_ref_count;
70+
qvi_hwpool_resource_id_hint_map_t resid_hint_map;
71+
};
72+
73+
/**
74+
* Base hardware pool resource class.
75+
*/
76+
struct qvi_hwpool_resource_s {
77+
/** Resource info. */
78+
qvi_hwpool_resource_info_s resinfo;
79+
/** Base constructor that does minimal work. */
80+
qvi_hwpool_resource_s(void) = default;
81+
/** Virtual destructor. */
82+
virtual ~qvi_hwpool_resource_s(void) = default;
83+
};
84+
85+
/**
86+
* Defines a cpuset pool.
87+
*/
88+
struct qvi_hwpool_cpus_s : qvi_hwpool_resource_s {
89+
int qvim_rc = QV_ERR_INTERNAL;
90+
/** The cpuset of the maintained CPUs. */
5391
hwloc_bitmap_t cpuset = nullptr;
92+
93+
qvi_hwpool_cpus_s(void)
94+
{
95+
qvim_rc = qvi_hwloc_bitmap_calloc(&cpuset);
96+
}
97+
98+
virtual
99+
~qvi_hwpool_cpus_s(void)
100+
{
101+
qvi_hwloc_bitmap_free(&cpuset);
102+
}
103+
};
104+
105+
struct qvi_hwpool_s {
106+
int qvim_rc = QV_ERR_INTERNAL;
107+
/** The CPUs in the resource pool. */
108+
qvi_hwpool_cpus_s cpus;
54109
/** Device information. */
55-
qvi_hwpool_devinfos_t *devinfos = nullptr;
110+
qvi_hwpool_devinfos_t devinfos;
56111
// TODO(skg) Add owner to structure?
57112
/** The obtained cpuset of this resource pool. */
58113
hwloc_bitmap_t obcpuset = nullptr;
114+
115+
qvi_hwpool_s(void)
116+
{
117+
qvim_rc = qvi_construct_rc(cpus);
118+
if (qvim_rc != QV_SUCCESS) return;
119+
120+
qvim_rc = qvi_hwloc_bitmap_calloc(&obcpuset);
121+
}
122+
123+
~qvi_hwpool_s(void)
124+
{
125+
qvi_hwloc_bitmap_free(&obcpuset);
126+
}
59127
};
60128

61129
int
62130
qvi_hwpool_new(
63131
qvi_hwpool_t **rpool
64132
) {
65-
int rc = QV_SUCCESS;
66-
67133
qvi_hwpool_t *irpool = qvi_new qvi_hwpool_t();
68-
if (!irpool) {
69-
rc = QV_ERR_OOR;
70-
goto out;
71-
}
72-
73-
irpool->devinfos = qvi_new qvi_hwpool_devinfos_t();
74-
if (!irpool->devinfos) {
75-
rc = QV_ERR_OOR;
76-
goto out;
77-
}
78-
79-
rc = qvi_hwloc_bitmap_calloc(&irpool->cpuset);
80-
if (rc != QV_SUCCESS) goto out;
81-
82-
rc = qvi_hwloc_bitmap_calloc(&irpool->obcpuset);
83-
out:
134+
int rc = qvi_new_rc(irpool);
84135
if (rc != QV_SUCCESS) {
85136
qvi_hwpool_free(&irpool);
86137
}
@@ -97,7 +148,7 @@ qvi_hwpool_new_from_line(
97148
int rc = qvi_hwpool_new(&irpool);
98149
if (rc != QV_SUCCESS) goto out;
99150

100-
rc = qvi_hwloc_bitmap_copy(line->cpuset, irpool->cpuset);
151+
rc = qvi_hwloc_bitmap_copy(line->cpuset, irpool->cpus.cpuset);
101152
if (rc != QV_SUCCESS) goto out;
102153

103154
for (int i = 0; i < line->ndevinfos; ++i) {
@@ -125,15 +176,15 @@ qvi_hwpool_new_line_from_hwpool(
125176
qvi_line_hwpool_t **line
126177
) {
127178
int rc = QV_SUCCESS;
128-
const int ndevinfos = rpool->devinfos->size();
179+
const int ndevinfos = rpool->devinfos.size();
129180

130181
qvi_line_hwpool_t *iline = nullptr;
131182
rc = qvi_line_hwpool_new(&iline);
132183
if (rc != QV_SUCCESS) goto out;
133184
// Initialize and copy the cpuset.
134185
rc = qvi_hwloc_bitmap_calloc(&iline->cpuset);
135186
if (rc != QV_SUCCESS) goto out;
136-
rc = qvi_hwloc_bitmap_copy(rpool->cpuset, iline->cpuset);
187+
rc = qvi_hwloc_bitmap_copy(rpool->cpus.cpuset, iline->cpuset);
137188
if (rc != QV_SUCCESS) goto out;
138189
// Initialize and fill in the device information.
139190
iline->ndevinfos = ndevinfos;
@@ -144,7 +195,7 @@ qvi_hwpool_new_line_from_hwpool(
144195
}
145196
do {
146197
int idx = 0, nw = 0;
147-
for (const auto &dinfo : *rpool->devinfos) {
198+
for (const auto &dinfo : rpool->devinfos) {
148199
iline->devinfos[idx].type = dinfo.second->type;
149200
iline->devinfos[idx].id = dinfo.second->id;
150201
// Initialize and copy cpuset
@@ -191,9 +242,6 @@ qvi_hwpool_free(
191242
if (!rpool) return;
192243
qvi_hwpool_t *irpool = *rpool;
193244
if (!irpool) goto out;
194-
delete irpool->devinfos;
195-
qvi_hwloc_bitmap_free(&irpool->cpuset);
196-
qvi_hwloc_bitmap_free(&irpool->obcpuset);
197245
delete irpool;
198246
out:
199247
*rpool = nullptr;
@@ -204,7 +252,7 @@ qvi_hwpool_init(
204252
qvi_hwpool_t *rpool,
205253
hwloc_const_bitmap_t cpuset
206254
) {
207-
return qvi_hwloc_bitmap_copy(cpuset, rpool->cpuset);
255+
return qvi_hwloc_bitmap_copy(cpuset, rpool->cpus.cpuset);
208256
}
209257

210258
int
@@ -216,7 +264,7 @@ qvi_hwpool_add_device(
216264
cstr_t uuid,
217265
hwloc_const_cpuset_t affinity
218266
) {
219-
rpool->devinfos->insert(
267+
rpool->devinfos.insert(
220268
std::make_pair(
221269
type,
222270
std::make_shared<qvi_devinfo_t>(
@@ -231,24 +279,24 @@ int
231279
qvi_hwpool_release_devices(
232280
qvi_hwpool_t *pool
233281
) {
234-
pool->devinfos->clear();
282+
pool->devinfos.clear();
235283
return QV_SUCCESS;
236284
}
237285

238286
hwloc_const_cpuset_t
239287
qvi_hwpool_cpuset_get(
240288
qvi_hwpool_t *rpool
241289
) {
242-
if (!rpool) return nullptr;
243-
return rpool->cpuset;
290+
assert(rpool);
291+
return rpool->cpus.cpuset;
244292
}
245293

246294
const qvi_hwpool_devinfos_t *
247295
qvi_hwpool_devinfos_get(
248296
qvi_hwpool_t *pool
249297
) {
250-
if (!pool) return nullptr;
251-
return pool->devinfos;
298+
assert(pool);
299+
return &pool->devinfos;
252300
}
253301

254302
#if 0
@@ -344,15 +392,15 @@ qvi_hwpool_add_devices_with_affinity(
344392
const qv_hw_obj_type_t type = devts[i];
345393
int nobjs = 0;
346394
rc = qvi_hwloc_get_nobjs_in_cpuset(
347-
hwloc, type, pool->cpuset, &nobjs
395+
hwloc, type, pool->cpus.cpuset, &nobjs
348396
);
349397
if (rc != QV_SUCCESS) break;
350398
// Iterate over the number of devices in each type.
351399
for (int devi = 0; devi < nobjs; ++devi) {
352400
char *devids = nullptr, *pcibid = nullptr, *uuids = nullptr;
353401
// Device ID
354402
rc = qvi_hwloc_get_device_in_cpuset(
355-
hwloc, type, devi, pool->cpuset,
403+
hwloc, type, devi, pool->cpus.cpuset,
356404
QV_DEVICE_ID_ORDINAL, &devids
357405
);
358406
if (rc != QV_SUCCESS) break;
@@ -362,13 +410,13 @@ qvi_hwpool_add_devices_with_affinity(
362410
if (rc != QV_SUCCESS) break;
363411
// PCI Bus ID
364412
rc = qvi_hwloc_get_device_in_cpuset(
365-
hwloc, type, devi, pool->cpuset,
413+
hwloc, type, devi, pool->cpus.cpuset,
366414
QV_DEVICE_ID_PCI_BUS_ID, &pcibid
367415
);
368416
if (rc != QV_SUCCESS) break;
369417
// UUID
370418
rc = qvi_hwloc_get_device_in_cpuset(
371-
hwloc, type, devi, pool->cpuset,
419+
hwloc, type, devi, pool->cpus.cpuset,
372420
QV_DEVICE_ID_UUID, &uuids
373421
);
374422
if (rc != QV_SUCCESS) break;

src/qvi-utils.h

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* -*- Mode: C++; c-basic-offset:4; indent-tabs-mode:nil -*- */
22
/*
3-
* Copyright (c) 2020-2022 Triad National Security, LLC
3+
* Copyright (c) 2020-2024 Triad National Security, LLC
44
* All rights reserved.
55
*
66
* Copyright (c) 2020-2021 Lawrence Livermore National Security, LLC
@@ -19,6 +19,39 @@
1919

2020
#include "qvi-common.h"
2121

22+
#ifdef __cplusplus
23+
24+
/**
25+
* Returns the code captured by a constructor. Since we are trying to avoid the
26+
* use of exceptions, we instead use this method for checking the state of an
27+
* object after its construction. This method isn't perfect, and requires that a
28+
* class member named qvim_rc (read as (qvi) (m)ember (r)eturn (c)ode) is
29+
* present in the provided class. Compilation will fail otherwise.
30+
*/
31+
template <class T>
32+
int
33+
qvi_construct_rc(
34+
const T &t
35+
) {
36+
return t.qvim_rc;
37+
}
38+
39+
/**
40+
* Similar to qvi_construct_rc(), but is used also to check the value returned
41+
* by qvi_new.
42+
*/
43+
template <class T>
44+
int
45+
qvi_new_rc(
46+
const T *const t
47+
) {
48+
// qvi_new must have returned nullptr.
49+
if (!t) return QV_ERR_OOR;
50+
return t->qvim_rc;
51+
}
52+
53+
#endif
54+
2255
#ifdef __cplusplus
2356
extern "C" {
2457
#endif

0 commit comments

Comments
 (0)