GCC Code Coverage Report


Directory: src/
File: src/LB_core/DLB_kernel.c
Date: 2025-11-21 10:34:40
Exec Total Coverage
Lines: 307 393 78.1%
Functions: 33 35 94.3%
Branches: 184 288 63.9%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2022 Barcelona Supercomputing Center */
3 /* */
4 /* This file is part of the DLB library. */
5 /* */
6 /* DLB is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU Lesser General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* DLB is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU Lesser General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU Lesser General Public License */
17 /* along with DLB. If not, see <https://www.gnu.org/licenses/>. */
18 /*********************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include "LB_core/DLB_kernel.h"
25
26 #include "LB_core/node_barrier.h"
27 #include "LB_core/spd.h"
28 #include "LB_numThreads/numThreads.h"
29 #include "LB_numThreads/omptool.h"
30 #include "LB_comm/shmem_async.h"
31 #include "LB_comm/shmem_barrier.h"
32 #include "LB_comm/shmem_cpuinfo.h"
33 #include "LB_comm/shmem_procinfo.h"
34 #include "LB_comm/shmem_talp.h"
35 #include "apis/dlb_errors.h"
36 #include "apis/dlb_talp.h"
37 #include "plugins/plugin_manager.h"
38 #include "support/debug.h"
39 #include "support/mytime.h"
40 #include "support/tracing.h"
41 #include "support/options.h"
42 #include "support/mask_utils.h"
43 #include "talp/talp.h"
44 #include "talp/talp_mpi.h"
45 #ifdef MPI_LIB
46 #include "mpi/mpi_core.h"
47 #endif
48
49 #include <limits.h>
50 #include <sched.h>
51 #include <string.h>
52
53
54 /* By default all threads are participants.
55 * A thread may change this value to avoid participating in LeWI and TALP metrics. */
56 __thread bool thread_is_observer = false;
57
58
59 /* Status */
60
61 92 int Initialize(subprocess_descriptor_t *spd, pid_t id, int ncpus,
62 const cpu_set_t *mask, const char *lb_args) {
63
64 92 int error = DLB_SUCCESS;
65
66 // Set it to false in case one thread is an observer but then Initializes DLB
67 92 thread_is_observer = false;
68
69 // Initialize common modules (spd->id and instrumentation module ASAP)
70 92 *spd = (const subprocess_descriptor_t) {
71 .id = id,
72 92 .pid = getpid(),
73 92 .dlb_initialized = spd->dlb_initialized,
74 92 .dlb_preinitialized = spd->dlb_preinitialized,
75 };
76 92 options_init(&spd->options, lb_args);
77 92 debug_init(&spd->options);
78 init_tracing(&spd->options);
79 instrument_event(RUNTIME_EVENT, EVENT_INIT, EVENT_BEGIN);
80 92 mu_init();
81 92 timer_init();
82
83 // Infer LeWI mode
84 92 spd->lb_policy =
85
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 32 times.
149 !spd->options.lewi ? POLICY_NONE :
86
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 spd->options.lewi_affinity == LEWI_AFFINITY_NONE ? POLICY_LEWI :
87
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 spd->options.lewi_affinity != LEWI_AFFINITY_AUTO ? POLICY_LEWI_MASK :
88
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 spd->options.ompt ? POLICY_LEWI_MASK :
89
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2 times.
55 spd->options.preinit_pid ? POLICY_LEWI_MASK :
90 mask ? POLICY_LEWI_MASK :
91 POLICY_LEWI;
92
93
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 60 times.
92 if (spd->lb_policy == POLICY_LEWI
94
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 27 times.
32 && spd->options.mode == MODE_ASYNC) {
95 5 spd->lb_policy = POLICY_LEWI_ASYNC;
96 }
97
98 // Check if real process mask is needed and possible incompatibilities
99 // (Basically, always except if classic LeWI)
100 92 bool mask_is_needed = (
101 92 spd->lb_policy == POLICY_LEWI_MASK
102
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 17 times.
67 || spd->options.drom
103
4/4
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 49 times.
159 || spd->options.preinit_pid);
104
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 49 times.
92 if (mask_is_needed &&
105
2/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
43 (spd->lb_policy == POLICY_LEWI || spd->lb_policy == POLICY_LEWI_ASYNC)) {
106 warning("Classic LeWI support with no cpuset binding is not compatible"
107 " with newer DLB modules. DLB_Init cannot continue.");
108 return DLB_ERR_NOCOMP;
109 }
110
111 // Initialize the rest of the subprocess descriptor
112 92 pm_init(&spd->pm);
113 92 set_lb_funcs(&spd->lb_funcs, spd->lb_policy);
114
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 41 times.
92 if (mask) {
115 // Preferred case, mask is provided by the user
116 51 memcpy(&spd->process_mask, mask, sizeof(cpu_set_t));
117 } else {
118 // Best effort querying the system
119 // (it may be late if DLB_Init is called after other RT sets this thread's affinity)
120 41 sched_getaffinity(0, sizeof(cpu_set_t), &spd->process_mask);
121 }
122
123 // ncpus is only used for classic LeWI
124
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 27 times.
92 if (spd->lb_policy == POLICY_LEWI
125
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 60 times.
65 || spd->lb_policy == POLICY_LEWI_ASYNC) {
126
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 4 times.
32 spd->lewi_ncpus = ncpus > 0 ? ncpus : pm_get_num_threads();
127 }
128
129 // Initialize shared memories
130
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 49 times.
92 if (mask_is_needed) {
131 // Initialize procinfo
132
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (spd->options.lewi_color == 0) {
133 cpu_set_t new_process_mask;
134 43 error = shmem_procinfo__init(spd->id, spd->options.preinit_pid,
135 43 &spd->process_mask, &new_process_mask, spd->options.shm_key,
136 spd->options.shm_size_multiplier);
137
138 // If the process has been pre-initialized (error=DLB_NOTED),
139 // the mask provided by shmem_procinfo__init must overwrite the process mask
140
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 35 times.
43 if (error == DLB_NOTED) {
141 8 set_process_mask(&spd->pm, &new_process_mask);
142 8 memcpy(&spd->process_mask, &new_process_mask, sizeof(cpu_set_t));
143 8 error = DLB_SUCCESS;
144 }
145 } else {
146 // If using --lewi-color, we also need to initialize procinfo with cpu sharing
147 error = shmem_procinfo__init_with_cpu_sharing(spd->id, spd->options.preinit_pid,
148 &spd->process_mask, spd->options.shm_key, spd->options.shm_size_multiplier);
149 }
150
151
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
43 if (error != DLB_SUCCESS) return error;
152
153 // Initialize cpuinfo
154 41 error = shmem_cpuinfo__init(spd->id, spd->options.preinit_pid,
155 41 &spd->process_mask, spd->options.shm_key, spd->options.lewi_color);
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (error != DLB_SUCCESS) return error;
157
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 43 times.
49 } else if (spd->options.talp) {
158 // If mask is not needed but TALP is enabled, we still need to
159 // initialize shmem_procinfo but allowing CPU sharing
160 6 error = shmem_procinfo__init_with_cpu_sharing(spd->id, spd->options.preinit_pid,
161 6 &spd->process_mask, spd->options.shm_key, spd->options.shm_size_multiplier);
162 }
163
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 3 times.
90 if (spd->options.barrier) {
164 87 shmem_barrier__init(spd->options.shm_key, spd->options.shm_size_multiplier);
165 87 node_barrier_init(spd);
166 }
167
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 79 times.
90 if (spd->options.mode == MODE_ASYNC) {
168 11 error = shmem_async_init(spd->id, &spd->pm, &spd->process_mask,
169 11 spd->options.shm_key, spd->options.shm_size_multiplier);
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (error != DLB_SUCCESS) return error;
171 }
172
173 // Initialise LeWI
174 90 error = spd->lb_funcs.init(spd);
175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 if (error != DLB_SUCCESS) return error;
176
177 // Initialize TALP
178
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 83 times.
90 if (spd->options.talp) {
179 7 talp_init(spd);
180 } else {
181 83 spd->talp_info = NULL;
182 }
183
184 // Initialize plugins
185 90 load_plugins(spd->options.plugins);
186
187 // Print initialization summary
188 90 info0("%s %s", PACKAGE, VERSION);
189
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 33 times.
90 if (spd->lb_policy != POLICY_NONE) {
190 57 info0("Balancing policy: %s", policy_tostr(spd->lb_policy));
191 57 options_print_lewi_flags(&spd->options);
192 }
193 instrument_print_flags();
194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_API, "Enabled verbose mode for DLB API");
195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_MPI_API, "Enabled verbose mode for MPI API");
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_MPI_INT, "Enabled verbose mode for MPI Interception");
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_SHMEM, "Enabled verbose mode for Shared Memory");
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_DROM, "Enabled verbose mode for DROM");
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_STATS, "Enabled verbose mode for STATS");
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_MICROLB, "Enabled verbose mode for microLB policies");
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_ASYNC, "Enabled verbose mode for Asynchronous thread");
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 verbose(VB_OMPT, "Enabled verbose mode for OMPT experimental features");
203
204 // Print number of cpus or mask
205
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 49 times.
90 if (mask_is_needed) {
206 41 info("Process CPU affinity mask: %s", mu_to_str(&spd->process_mask));
207 }
208
209 90 spd->lewi_enabled = true;
210 instrument_event(RUNTIME_EVENT, EVENT_INIT, EVENT_END);
211 instrument_event(DLB_MODE_EVENT, EVENT_ENABLED, EVENT_BEGIN);
212
213 90 return error;
214 }
215
216 90 int Finish(subprocess_descriptor_t *spd) {
217
218 /* Protect finalization if spd does not match with current process */
219
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
90 if (spd->pid != getpid()) {
220 return DLB_NOUPDT;
221 }
222
223 90 int error = DLB_SUCCESS;
224 instrument_event(RUNTIME_EVENT, EVENT_FINALIZE, EVENT_BEGIN);
225
226 #if MPI_LIB
227 /* If DLB_Finalize is called preemptively, we need to finalize also the MPI
228 * module */
229 finalize_mpi_core();
230 #endif
231
232 90 spd->lewi_enabled = false;
233
234 90 pm_finalize(&spd->pm);
235
236 // Finalize plugins
237 90 unload_plugins(spd->options.plugins);
238
239
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 83 times.
90 if (spd->options.talp) {
240 7 talp_finalize(spd);
241 }
242
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 if (spd->lb_funcs.finalize) {
243 90 spd->lb_funcs.finalize(spd);
244 90 spd->lb_funcs.finalize = NULL;
245 }
246
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 3 times.
90 if (spd->options.barrier) {
247 87 node_barrier_finalize(spd);
248 87 shmem_barrier__finalize(spd->options.shm_key, spd->options.shm_size_multiplier);
249 }
250
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 25 times.
90 if (spd->lb_policy == POLICY_LEWI_MASK
251
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 15 times.
65 || spd->options.drom
252
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 6 times.
50 || spd->options.talp
253
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 2 times.
44 || spd->options.ompt
254
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 || spd->options.preinit_pid) {
255 49 shmem_cpuinfo__finalize(spd->id, spd->options.shm_key, spd->options.lewi_color);
256 49 shmem_procinfo__finalize(spd->id, spd->options.debug_opts & DBG_RETURNSTOLEN,
257 49 spd->options.shm_key, spd->options.shm_size_multiplier);
258 }
259
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 79 times.
90 if (spd->options.mode == MODE_ASYNC) {
260 11 shmem_async_finalize(spd->id);
261 }
262 90 timer_finalize();
263 instrument_event(RUNTIME_EVENT, EVENT_FINALIZE, EVENT_END);
264 instrument_finalize();
265 90 options_finalize(&spd->options);
266 90 return error;
267 }
268
269 5 int PreInitialize(subprocess_descriptor_t *spd, const cpu_set_t *mask,
270 const char *lb_args) {
271 // Initialize options
272 5 options_init(&spd->options, lb_args);
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (spd->options.preinit_pid == 0) return DLB_ERR_INIT;
274
275 5 debug_init(&spd->options);
276
277 // Initialize subprocess descriptor
278 5 spd->lb_policy = POLICY_NONE;
279 5 pm_init(&spd->pm);
280 5 set_lb_funcs(&spd->lb_funcs, spd->lb_policy);
281 5 spd->id = spd->options.preinit_pid;
282 5 memcpy(&spd->process_mask, mask, sizeof(cpu_set_t));
283
284 // Initialize modules
285 5 int error = DLB_SUCCESS;
286
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 error = error ? error : shmem_cpuinfo_ext__init(spd->options.shm_key, spd->options.lewi_color);
287
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 error = error ? error : shmem_procinfo_ext__init(spd->options.shm_key,
288 spd->options.shm_size_multiplier);
289
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 error = error ? error : shmem_procinfo_ext__preinit(spd->id, mask, DLB_DROM_FLAGS_NONE);
290
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 error = error ? error : shmem_cpuinfo_ext__preinit(spd->id, mask, DLB_DROM_FLAGS_NONE);
291 // Close shmems even if there was an error
292 5 int cpuinfo_finalize_err = shmem_cpuinfo_ext__finalize();
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 error = error ? error : cpuinfo_finalize_err;
294 5 int procinfo_finalize_err = shmem_procinfo_ext__finalize();
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 error = error ? error : procinfo_finalize_err;
296 5 return error;
297 }
298
299 18 int set_lewi_enabled(subprocess_descriptor_t *spd, bool enabled) {
300 18 int error = DLB_SUCCESS;
301
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 if (__sync_bool_compare_and_swap(&spd->lewi_enabled, !enabled, enabled)) {
302
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (enabled) {
303 7 spd->lb_funcs.enable(spd);
304 instrument_event(DLB_MODE_EVENT, EVENT_ENABLED, EVENT_BEGIN);
305 } else {
306 7 spd->lb_funcs.disable(spd);
307 instrument_event(DLB_MODE_EVENT, EVENT_DISABLED, EVENT_BEGIN);
308 }
309 } else {
310 4 error = DLB_NOUPDT;
311 }
312 18 return error;
313 }
314
315 5 int set_max_parallelism(subprocess_descriptor_t *spd, int max) {
316 int error;
317
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!spd->options.lewi) {
318 3 error = DLB_ERR_NOLEWI;
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!spd->lewi_enabled) {
320 error = DLB_ERR_DISBLD;
321 } else {
322 instrument_event(RUNTIME_EVENT, EVENT_MAX_PARALLELISM, EVENT_BEGIN);
323 instrument_event(MAX_PAR_EVENT, 0, EVENT_END);
324 instrument_event(MAX_PAR_EVENT, max, EVENT_BEGIN);
325 2 error = spd->lb_funcs.set_max_parallelism(spd, max);
326 instrument_event(RUNTIME_EVENT, EVENT_MAX_PARALLELISM, EVENT_END);
327 }
328 5 return error;
329 }
330
331 3 int unset_max_parallelism(subprocess_descriptor_t *spd) {
332 int error;
333
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!spd->options.lewi) {
334 1 error = DLB_ERR_NOLEWI;
335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!spd->lewi_enabled) {
336 error = DLB_ERR_DISBLD;
337 } else {
338 instrument_event(RUNTIME_EVENT, EVENT_MAX_PARALLELISM, EVENT_BEGIN);
339 instrument_event(MAX_PAR_EVENT, 0, EVENT_END);
340 2 error = spd->lb_funcs.unset_max_parallelism(spd);
341 instrument_event(RUNTIME_EVENT, EVENT_MAX_PARALLELISM, EVENT_END);
342 }
343 3 return error;
344 }
345
346
347 /* Sync-call specific (MPI, DLB_Barrier, etc.) */
348
349 18 void into_sync_call(sync_call_flags_t flags) {
350 /* Observer threads do not trigger LeWI nor TALP on sync calls */
351
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (unlikely(thread_is_observer)) return;
352
353 16 const subprocess_descriptor_t *spd = thread_spd;
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (unlikely(spd == NULL)) return;
355
356
3/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 if (spd->options.lewi && spd->lewi_enabled && flags.do_lewi) {
357 16 spd->lb_funcs.into_blocking_call(spd);
358 16 omptool__into_blocking_call();
359 }
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if(spd->options.talp) {
361 talp_into_sync_call(spd, flags.is_blocking && flags.is_collective);
362 }
363 }
364
365 18 void out_of_sync_call(sync_call_flags_t flags) {
366 /* Observer threads do not trigger LeWI nor TALP on MPI calls */
367
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (unlikely(thread_is_observer)) return;
368
369 16 const subprocess_descriptor_t *spd = thread_spd;
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (unlikely(spd == NULL)) return;
371
372
3/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 if (spd->options.lewi && spd->lewi_enabled && flags.do_lewi) {
373 16 spd->lb_funcs.out_of_blocking_call(spd);
374 16 omptool__outof_blocking_call();
375 }
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if(spd->options.talp) {
377 talp_out_of_sync_call(spd, flags.is_blocking && flags.is_collective);
378 }
379 }
380
381
382 /* Lend */
383
384 8 int lend(const subprocess_descriptor_t *spd) {
385 int error;
386
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (!spd->options.lewi) {
387 6 error = DLB_ERR_NOLEWI;
388
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } else if (!spd->lewi_enabled) {
389 2 error = DLB_ERR_DISBLD;
390 } else {
391 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_BEGIN);
392 instrument_event(GIVE_CPUS_EVENT, CPU_SETSIZE, EVENT_BEGIN);
393 omptool__lend_from_api();
394 error = spd->lb_funcs.lend(spd);
395 instrument_event(GIVE_CPUS_EVENT, 0, EVENT_END);
396 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_END);
397 }
398 8 return error;
399 }
400
401 40 int lend_cpu(const subprocess_descriptor_t *spd, int cpuid) {
402 int error;
403
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 37 times.
40 if (!spd->options.lewi) {
404 3 error = DLB_ERR_NOLEWI;
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 } else if (!spd->lewi_enabled) {
406 error = DLB_ERR_DISBLD;
407 } else {
408 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_BEGIN);
409 instrument_event(GIVE_CPUS_EVENT, 1, EVENT_BEGIN);
410 37 error = spd->lb_funcs.lend_cpu(spd, cpuid);
411 instrument_event(GIVE_CPUS_EVENT, 0, EVENT_END);
412 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_END);
413 }
414 40 return error;
415 }
416
417 6 int lend_cpus(const subprocess_descriptor_t *spd, int ncpus) {
418 int error;
419
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!spd->options.lewi) {
420 3 error = DLB_ERR_NOLEWI;
421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (!spd->lewi_enabled) {
422 error = DLB_ERR_DISBLD;
423 } else {
424 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_BEGIN);
425 instrument_event(GIVE_CPUS_EVENT, ncpus, EVENT_BEGIN);
426 3 error = spd->lb_funcs.lend_cpus(spd, ncpus);
427 instrument_event(GIVE_CPUS_EVENT, 0, EVENT_END);
428 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_END);
429 }
430 6 return error;
431 }
432
433 18 int lend_cpu_mask(const subprocess_descriptor_t *spd, const cpu_set_t *mask) {
434 int error;
435
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
18 if (!spd->options.lewi) {
436 3 error = DLB_ERR_NOLEWI;
437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 } else if (!spd->lewi_enabled) {
438 error = DLB_ERR_DISBLD;
439 } else {
440 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_BEGIN);
441 instrument_event(GIVE_CPUS_EVENT, CPU_COUNT(mask), EVENT_BEGIN);
442 15 error = spd->lb_funcs.lend_cpu_mask(spd, mask);
443 instrument_event(GIVE_CPUS_EVENT, 0, EVENT_END);
444 instrument_event(RUNTIME_EVENT, EVENT_LEND, EVENT_END);
445 }
446 18 return error;
447 }
448
449
450 /* Reclaim */
451
452 6 int reclaim(const subprocess_descriptor_t *spd) {
453 int error;
454
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!spd->options.lewi) {
455 3 error = DLB_ERR_NOLEWI;
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (!spd->lewi_enabled) {
457 error = DLB_ERR_DISBLD;
458 } else {
459 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_BEGIN);
460 instrument_event(WANT_CPUS_EVENT, CPU_SETSIZE, EVENT_BEGIN);
461 3 error = spd->lb_funcs.reclaim(spd);
462 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
463 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_END);
464 }
465 6 return error;
466 }
467
468 5 int reclaim_cpu(const subprocess_descriptor_t *spd, int cpuid) {
469 int error;
470
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!spd->options.lewi) {
471 3 error = DLB_ERR_NOLEWI;
472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!spd->lewi_enabled) {
473 error = DLB_ERR_DISBLD;
474 } else {
475 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_BEGIN);
476 instrument_event(WANT_CPUS_EVENT, 1, EVENT_BEGIN);
477 2 error = spd->lb_funcs.reclaim_cpu(spd, cpuid);
478 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
479 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_END);
480 }
481 5 return error;
482 }
483
484 3 int reclaim_cpus(const subprocess_descriptor_t *spd, int ncpus) {
485 int error;
486
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!spd->options.lewi) {
487 3 error = DLB_ERR_NOLEWI;
488 } else if (!spd->lewi_enabled) {
489 error = DLB_ERR_DISBLD;
490 } else {
491 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_BEGIN);
492 instrument_event(WANT_CPUS_EVENT, ncpus, EVENT_BEGIN);
493 error = spd->lb_funcs.reclaim_cpus(spd, ncpus);
494 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
495 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_END);
496 }
497 3 return error;
498 }
499
500 8 int reclaim_cpu_mask(const subprocess_descriptor_t *spd, const cpu_set_t *mask) {
501 int error;
502
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (!spd->options.lewi) {
503 3 error = DLB_ERR_NOLEWI;
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (!spd->lewi_enabled) {
505 error = DLB_ERR_DISBLD;
506 } else {
507 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_BEGIN);
508 instrument_event(WANT_CPUS_EVENT, CPU_COUNT(mask), EVENT_BEGIN);
509 5 error = spd->lb_funcs.reclaim_cpu_mask(spd, mask);
510 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
511 instrument_event(RUNTIME_EVENT, EVENT_RECLAIM, EVENT_END);
512 }
513 8 return error;
514 }
515
516
517 /* Acquire */
518
519 13 int acquire_cpu(const subprocess_descriptor_t *spd, int cpuid) {
520 int error;
521
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (!spd->options.lewi) {
522 3 error = DLB_ERR_NOLEWI;
523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 } else if (!spd->lewi_enabled) {
524 error = DLB_ERR_DISBLD;
525 } else {
526 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_BEGIN);
527 instrument_event(WANT_CPUS_EVENT, 1, EVENT_BEGIN);
528 10 error = spd->lb_funcs.acquire_cpu(spd, cpuid);
529 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
530 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_END);
531 }
532 13 return error;
533 }
534
535 61 int acquire_cpus(const subprocess_descriptor_t *spd, int ncpus) {
536 int error;
537
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 58 times.
61 if (!spd->options.lewi) {
538 3 error = DLB_ERR_NOLEWI;
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 } else if (!spd->lewi_enabled) {
540 error = DLB_ERR_DISBLD;
541 } else {
542 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_BEGIN);
543 instrument_event(WANT_CPUS_EVENT, ncpus, EVENT_BEGIN);
544 58 error = spd->lb_funcs.acquire_cpus(spd, ncpus);
545 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
546 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_END);
547 }
548 61 return error;
549 }
550
551 12 int acquire_cpu_mask(const subprocess_descriptor_t *spd, const cpu_set_t *mask) {
552 int error;
553
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (!spd->options.lewi) {
554 3 error = DLB_ERR_NOLEWI;
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (!spd->lewi_enabled) {
556 error = DLB_ERR_DISBLD;
557 } else {
558 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_BEGIN);
559 instrument_event(WANT_CPUS_EVENT, CPU_COUNT(mask), EVENT_BEGIN);
560 9 error = spd->lb_funcs.acquire_cpu_mask(spd, mask);
561 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
562 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_END);
563 }
564 12 return error;
565 }
566
567 14 int acquire_cpus_in_mask(const subprocess_descriptor_t *spd, int ncpus, const cpu_set_t *mask) {
568 int error;
569
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
14 if (!spd->options.lewi) {
570 3 error = DLB_ERR_NOLEWI;
571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 } else if (!spd->lewi_enabled) {
572 error = DLB_ERR_DISBLD;
573 } else {
574 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_BEGIN);
575 instrument_event(WANT_CPUS_EVENT, ncpus, EVENT_BEGIN);
576 11 error = spd->lb_funcs.acquire_cpus_in_mask(spd, ncpus, mask);
577 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
578 instrument_event(RUNTIME_EVENT, EVENT_ACQUIRE, EVENT_END);
579 }
580 14 return error;
581 }
582
583
584 /* Borrow */
585
586 7 int borrow(const subprocess_descriptor_t *spd) {
587 int error;
588
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (!spd->options.lewi) {
589 3 error = DLB_ERR_NOLEWI;
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (!spd->lewi_enabled) {
591 error = DLB_ERR_DISBLD;
592 } else {
593 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_BEGIN);
594 instrument_event(WANT_CPUS_EVENT, CPU_SETSIZE, EVENT_BEGIN);
595 4 error = spd->lb_funcs.borrow(spd);
596 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
597 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_END);
598 }
599 7 return error;
600 }
601
602 3 int borrow_cpu(const subprocess_descriptor_t *spd, int cpuid) {
603 int error;
604
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!spd->options.lewi) {
605 3 error = DLB_ERR_NOLEWI;
606 } else if (!spd->lewi_enabled) {
607 error = DLB_ERR_DISBLD;
608 } else {
609 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_BEGIN);
610 instrument_event(WANT_CPUS_EVENT, 1, EVENT_BEGIN);
611 error = spd->lb_funcs.borrow_cpu(spd, cpuid);
612 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
613 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_END);
614 }
615 3 return error;
616 }
617
618 3 int borrow_cpus(const subprocess_descriptor_t *spd, int ncpus) {
619 int error;
620
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!spd->options.lewi) {
621 3 error = DLB_ERR_NOLEWI;
622 } else if (!spd->lewi_enabled) {
623 error = DLB_ERR_DISBLD;
624 } else {
625 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_BEGIN);
626 instrument_event(WANT_CPUS_EVENT, ncpus, EVENT_BEGIN);
627 error = spd->lb_funcs.borrow_cpus(spd, ncpus);
628 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
629 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_END);
630 }
631 3 return error;
632 }
633
634 3 int borrow_cpu_mask(const subprocess_descriptor_t *spd, const cpu_set_t *mask) {
635 int error;
636
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!spd->options.lewi) {
637 3 error = DLB_ERR_NOLEWI;
638 } else if (!spd->lewi_enabled) {
639 error = DLB_ERR_DISBLD;
640 } else {
641 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_BEGIN);
642 instrument_event(WANT_CPUS_EVENT, CPU_COUNT(mask), EVENT_BEGIN);
643 error = spd->lb_funcs.borrow_cpu_mask(spd, mask);
644 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
645 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_END);
646 }
647 3 return error;
648 }
649
650 7 int borrow_cpus_in_mask(const subprocess_descriptor_t *spd, int ncpus, const cpu_set_t *mask) {
651 int error;
652
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (!spd->options.lewi) {
653 3 error = DLB_ERR_NOLEWI;
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (!spd->lewi_enabled) {
655 error = DLB_ERR_DISBLD;
656 } else {
657 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_BEGIN);
658 instrument_event(WANT_CPUS_EVENT, ncpus, EVENT_BEGIN);
659 4 error = spd->lb_funcs.borrow_cpus_in_mask(spd, ncpus, mask);
660 instrument_event(WANT_CPUS_EVENT, 0, EVENT_END);
661 instrument_event(RUNTIME_EVENT, EVENT_BORROW, EVENT_END);
662 }
663 7 return error;
664 }
665
666 /* Return */
667
668 3 int return_all(const subprocess_descriptor_t *spd) {
669 int error;
670
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!spd->options.lewi) {
671 3 error = DLB_ERR_NOLEWI;
672 } else if (!spd->lewi_enabled) {
673 error = DLB_ERR_DISBLD;
674 } else {
675 instrument_event(RUNTIME_EVENT, EVENT_RETURN, EVENT_BEGIN);
676 error = spd->lb_funcs.return_all(spd);
677 instrument_event(RUNTIME_EVENT, EVENT_RETURN, EVENT_END);
678 }
679 3 return error;
680 }
681
682 19 int return_cpu(const subprocess_descriptor_t *spd, int cpuid) {
683 int error;
684
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16 times.
19 if (!spd->options.lewi) {
685 3 error = DLB_ERR_NOLEWI;
686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 } else if (!spd->lewi_enabled) {
687 error = DLB_ERR_DISBLD;
688 } else {
689 instrument_event(RUNTIME_EVENT, EVENT_RETURN, EVENT_BEGIN);
690 16 error = spd->lb_funcs.return_cpu(spd, cpuid);
691 instrument_event(RUNTIME_EVENT, EVENT_RETURN, EVENT_END);
692 }
693 19 return error;
694 }
695
696 3 int return_cpu_mask(const subprocess_descriptor_t *spd, const cpu_set_t *mask) {
697 int error;
698
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!spd->options.lewi) {
699 3 error = DLB_ERR_NOLEWI;
700 } else if (!spd->lewi_enabled) {
701 error = DLB_ERR_DISBLD;
702 } else {
703 instrument_event(RUNTIME_EVENT, EVENT_RETURN, EVENT_BEGIN);
704 error = spd->lb_funcs.return_cpu_mask(spd, mask);
705 instrument_event(RUNTIME_EVENT, EVENT_RETURN, EVENT_END);
706 }
707 3 return error;
708 }
709
710
711 /* Drom Responsive */
712
713 5 int poll_drom(const subprocess_descriptor_t *spd, int *new_cpus, cpu_set_t *new_mask) {
714 int error;
715
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!spd->options.drom) {
716 2 error = DLB_ERR_NOCOMP;
717 } else {
718 instrument_event(RUNTIME_EVENT, EVENT_POLLDROM, EVENT_BEGIN);
719 // Use a local mask if new_mask was not provided
720 cpu_set_t local_mask;
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 cpu_set_t *mask = new_mask ? new_mask : &local_mask;
722
723 3 error = shmem_procinfo__polldrom(spd->id, new_cpus, mask);
724
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (error == DLB_SUCCESS) {
725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (spd->options.lewi) {
726 /* If LeWI, resolve reclaimed CPUs */
727 spd->lb_funcs.update_ownership(spd, mask);
728 } else {
729 /* Otherwise, udate owner and guest data */
730 1 shmem_cpuinfo__update_ownership(spd->id, mask, NULL);
731 }
732 }
733 instrument_event(RUNTIME_EVENT, EVENT_POLLDROM, EVENT_END);
734 }
735 5 return error;
736 }
737
738 int poll_drom_update(const subprocess_descriptor_t *spd) {
739 cpu_set_t new_mask;
740 int error = poll_drom(spd, NULL, &new_mask);
741 if (error == DLB_SUCCESS) {
742 set_process_mask(&spd->pm, &new_mask);
743 }
744 return error;
745 }
746
747 14 int drom_setprocessmask(int pid, const_dlb_cpu_set_t mask, dlb_drom_flags_t flags) {
748 cpu_set_t free_cpu_mask;
749 14 int error = shmem_procinfo__setprocessmask(pid, mask, flags, &free_cpu_mask);
750
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (error == DLB_SUCCESS
751
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 && thread_spd->dlb_initialized
752
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 && (pid == 0 || pid == thread_spd->id)
753
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 && !(flags & DLB_NO_SYNC)) {
754 /* Mask has been successfully set by own process, do like a poll_drom_update */
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (thread_spd->options.lewi) {
756 /* If LeWI, resolve reclaimed CPUs */
757 thread_spd->lb_funcs.update_ownership(thread_spd, mask);
758 } else {
759 /* Otherwise, udate owner and guest data */
760 2 shmem_cpuinfo__update_ownership(thread_spd->id, mask, NULL);
761 }
762 2 set_process_mask(&thread_spd->pm, mask);
763 }
764
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
14 if (error == DLB_SUCCESS && (flags & DLB_FREE_CPUS_SLURM)) {
765 // Slurm freeing
766 char *mask_str = mu_parse_to_slurm_format(&free_cpu_mask);
767 if (mask_str == NULL) {
768 warning("error parsing mask %s to Slurm format", mu_to_str(&free_cpu_mask));
769 return DLB_ERR_UNKNOWN;
770 }
771 if (!secure_getenv("SLURM_JOBID")) {
772 warning("SLURM_JOBID is mandatory");
773 return DLB_ERR_UNKNOWN;
774 }
775 char hostname[HOST_NAME_MAX];
776 gethostname(hostname, HOST_NAME_MAX);
777 char *args[5];
778 asprintf(&args[0], "scontrol");
779 asprintf(&args[1], "update");
780 asprintf(&args[2], "jobid=%s", secure_getenv("SLURM_JOBID"));
781 asprintf(&args[3], "dealloc=%s:%s", hostname, mask_str);
782 args[4] = NULL;
783
784 int res_pid = fork();
785 if (res_pid < 0) {
786 warning("fork error while invoking scontrol");
787 return DLB_ERR_UNKNOWN;
788 } else if (res_pid == 0) {
789 verbose(VB_DROM, "%s %s %s %s", args[0], args[1], args[2], args[3]);
790 execvp("scontrol", args);
791 }
792
793 for (int i = 0; i < 5; ++i) {
794 free(args[i]);
795 }
796 free(mask_str);
797 }
798
799 14 return error;
800 }
801
802
803 /* Misc */
804
805 24 int check_cpu_availability(const subprocess_descriptor_t *spd, int cpuid) {
806 24 int error = DLB_SUCCESS;
807
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 23 times.
24 if (!spd->options.lewi) {
808 1 error = DLB_ERR_NOLEWI;
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 } else if (!spd->lewi_enabled) {
810 error = DLB_ERR_DISBLD;
811 } else {
812 23 error = spd->lb_funcs.check_cpu_availability(spd, cpuid);
813 }
814 24 return error;
815 }
816
817 6 int print_shmem(subprocess_descriptor_t *spd, int num_columns,
818 dlb_printshmem_flags_t print_flags) {
819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!spd->dlb_initialized) {
820 options_init(&spd->options, NULL);
821 debug_init(&spd->options);
822 }
823
824 6 shmem_cpuinfo__print_info(spd->options.shm_key, spd->options.lewi_color,
825 num_columns, print_flags);
826 6 shmem_procinfo__print_info(spd->options.shm_key, spd->options.shm_size_multiplier);
827 6 shmem_barrier__print_info(spd->options.shm_key, spd->options.shm_size_multiplier);
828 6 shmem_talp__print_info(spd->options.shm_key, spd->options.shm_size_multiplier);
829
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!spd->dlb_initialized) {
831 options_finalize(&spd->options);
832 }
833
834 6 return DLB_SUCCESS;
835 }
836
837 11 int set_observer_role(bool is_observer) {
838 11 thread_is_observer = is_observer;
839 11 return DLB_SUCCESS;
840 }
841
842 int get_gpu_affinity(char *buffer, size_t buffer_size, bool full_uuid) {
843 int error = DLB_SUCCESS;
844 if (load_plugin("cupti") == DLB_SUCCESS) {
845 plugin_get_gpu_affinity(buffer, buffer_size, full_uuid);
846 unload_plugin("cupti");
847 } else if (load_plugin("rocprofilerv2") == DLB_SUCCESS) {
848 plugin_get_gpu_affinity(buffer, buffer_size, full_uuid);
849 unload_plugin("rocprofilerv2");
850 } else {
851 error = DLB_ERR_UNKNOWN;
852 }
853
854 return error;
855 }
856