GCC Code Coverage Report


Directory: src/
File: src/apis/DLB_interface.c
Date: 2026-09-15 07:37:49
Exec Total Coverage
Lines: 175 221 79.2%
Functions: 43 49 87.8%
Branches: 40 76 52.6%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2024 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 "apis/dlb.h"
25
26 #include "LB_core/node_barrier.h"
27 #include "LB_core/spd.h"
28 #include "LB_core/thread_ctx.h"
29 #include "LB_core/DLB_kernel.h"
30 #include "LB_comm/shmem_procinfo.h"
31 #include "support/env.h"
32 #include "support/error.h"
33 #include "support/dlb_common.h"
34 #include "support/options.h"
35
36 #include <unistd.h>
37 #include <stdbool.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41
42
43 /* Auto-init */
44 static void dlb_auto_finalize(void) {
45 DLB_Finalize();
46 }
47
48 __attribute__((constructor))
49 96 static void dlb_auto_init(void) {
50 96 const char *dlb_auto_init_env_var = getenv("DLB_AUTO_INIT");
51
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96 if (dlb_auto_init_env_var != NULL && dlb_auto_init_env_var[0] == '1') {
52 if (DLB_Init(0, 0, 0) == DLB_SUCCESS) {
53 // Finalize DLB before other destructors are invoked
54 atexit(dlb_auto_finalize);
55 }
56 }
57 96 }
58
59 /* Status */
60
61 DLB_EXPORT_SYMBOL
62 44 int DLB_Init(int ncpus, const_dlb_cpu_set_t mask, const char *dlb_args) {
63 44 spd_enter_dlb(thread_spd);
64
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 3 times.
44 if (__sync_bool_compare_and_swap(&thread_spd->dlb_initialized, false, true) ) {
65 41 return Initialize(thread_spd, getpid(), ncpus, mask, dlb_args);
66 } else {
67 3 return DLB_ERR_INIT;
68 }
69 }
70
71 DLB_EXPORT_SYMBOL
72 48 int DLB_Finalize(void) {
73 48 spd_enter_dlb(thread_spd);
74
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7 times.
48 if (__sync_bool_compare_and_swap(&thread_spd->dlb_initialized, true, false) ) {
75 41 return Finish(thread_spd);
76
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 } else if (__sync_bool_compare_and_swap(&thread_spd->dlb_preinitialized, true, false) ) {
77 /* This is to support the case when a single process does DLB_PreInit + DLB_Init
78 * The first DLB_Finalize must finalize everything except the CPUs not inherited
79 * during DLB_Init, if any. The second finalize must clean up the procinfo shmem.
80 */
81 5 shmem_procinfo__finalize(thread_spd->id,
82 5 thread_spd->options.debug_opts & DBG_RETURNSTOLEN,
83 5 thread_spd->options.shm_key,
84 5 thread_spd->options.shm_size_multiplier);
85 5 return DLB_SUCCESS;
86 }
87 2 return DLB_NOUPDT;
88 }
89
90 DLB_EXPORT_SYMBOL
91 5 int DLB_PreInit(const_dlb_cpu_set_t mask, char ***next_environ) {
92 5 spd_enter_dlb(thread_spd);
93
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!thread_spd->dlb_initialized
94
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 && __sync_bool_compare_and_swap(&thread_spd->dlb_preinitialized, false, true)) {
95
96 /* DLB_PreInit must modify the environment so that a process child
97 * knows what CPUs must inherit */
98 char flag[32];
99 5 snprintf(flag, 32, "--preinit-pid=%d", getpid());
100 5 dlb_setenv("DLB_ARGS", flag, next_environ, ENV_APPEND);
101
102 5 return PreInitialize(thread_spd, mask, NULL);
103 } else {
104 return DLB_ERR_INIT;
105 }
106 }
107
108 DLB_EXPORT_SYMBOL
109 3 int DLB_Enable(void) {
110 3 spd_enter_dlb(thread_spd);
111
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (unlikely(!thread_spd->dlb_initialized)) {
112 1 return DLB_ERR_NOINIT;
113 }
114 2 return set_lewi_enabled(thread_spd, true);
115 }
116
117 DLB_EXPORT_SYMBOL
118 2 int DLB_Disable(void) {
119 2 spd_enter_dlb(thread_spd);
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
121 return DLB_ERR_NOINIT;
122 }
123 2 return set_lewi_enabled(thread_spd, false);
124 }
125
126 DLB_EXPORT_SYMBOL
127 2 int DLB_SetMaxParallelism(int max) {
128 2 spd_enter_dlb(thread_spd);
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
130 return DLB_ERR_NOINIT;
131 }
132 2 return set_max_parallelism(thread_spd, max);
133 }
134
135 DLB_EXPORT_SYMBOL
136 1 int DLB_UnsetMaxParallelism(void) {
137 1 spd_enter_dlb(thread_spd);
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (unlikely(!thread_spd->dlb_initialized)) {
139 return DLB_ERR_NOINIT;
140 }
141 1 return unset_max_parallelism(thread_spd);
142 }
143
144
145 /* Callbacks */
146
147 DLB_EXPORT_SYMBOL
148 45 int DLB_CallbackSet(dlb_callbacks_t which, dlb_callback_t callback, void *arg) {
149 45 spd_enter_dlb(thread_spd);
150 45 return pm_callback_set(&thread_spd->pm, which, callback, arg);
151 }
152
153 DLB_EXPORT_SYMBOL
154 1 int DLB_CallbackGet(dlb_callbacks_t which, dlb_callback_t *callback, void **arg) {
155 1 spd_enter_dlb(thread_spd);
156 1 return pm_callback_get(&thread_spd->pm, which, callback, arg);
157 }
158
159
160 /* Lend */
161
162 DLB_EXPORT_SYMBOL
163 4 int DLB_Lend(void) {
164 4 spd_enter_dlb(thread_spd);
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (unlikely(!thread_spd->dlb_initialized)) {
166 return DLB_ERR_NOINIT;
167 }
168 4 return lend(thread_spd);
169 }
170
171 DLB_EXPORT_SYMBOL
172 6 int DLB_LendCpu(int cpuid) {
173 6 spd_enter_dlb(thread_spd);
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (unlikely(!thread_spd->dlb_initialized)) {
175 return DLB_ERR_NOINIT;
176 }
177 6 return lend_cpu(thread_spd, cpuid);
178 }
179
180 DLB_EXPORT_SYMBOL
181 2 int DLB_LendCpus(int ncpus) {
182 2 spd_enter_dlb(thread_spd);
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
184 return DLB_ERR_NOINIT;
185 }
186 2 return lend_cpus(thread_spd, ncpus);
187 }
188
189 DLB_EXPORT_SYMBOL
190 4 int DLB_LendCpuMask(const_dlb_cpu_set_t mask) {
191 4 spd_enter_dlb(thread_spd);
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (unlikely(!thread_spd->dlb_initialized)) {
193 return DLB_ERR_NOINIT;
194 }
195 4 return lend_cpu_mask(thread_spd, mask);
196 }
197
198
199 /* Reclaim */
200
201 DLB_EXPORT_SYMBOL
202 3 int DLB_Reclaim(void) {
203 3 spd_enter_dlb(thread_spd);
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (unlikely(!thread_spd->dlb_initialized)) {
205 return DLB_ERR_NOINIT;
206 }
207 3 return reclaim(thread_spd);
208 }
209
210 DLB_EXPORT_SYMBOL
211 2 int DLB_ReclaimCpu(int cpuid) {
212 2 spd_enter_dlb(thread_spd);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
214 return DLB_ERR_NOINIT;
215 }
216 2 return reclaim_cpu(thread_spd, cpuid);
217 }
218
219 DLB_EXPORT_SYMBOL
220 2 int DLB_ReclaimCpus(int ncpus) {
221 2 spd_enter_dlb(thread_spd);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
223 return DLB_ERR_NOINIT;
224 }
225 2 return reclaim_cpus(thread_spd, ncpus);
226 }
227
228 DLB_EXPORT_SYMBOL
229 3 int DLB_ReclaimCpuMask(const_dlb_cpu_set_t mask) {
230 3 spd_enter_dlb(thread_spd);
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (unlikely(!thread_spd->dlb_initialized)) {
232 return DLB_ERR_NOINIT;
233 }
234 3 return reclaim_cpu_mask(thread_spd, mask);
235 }
236
237
238 /* Acquire */
239
240 DLB_EXPORT_SYMBOL
241 3 int DLB_AcquireCpu(int cpuid) {
242 3 spd_enter_dlb(thread_spd);
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (unlikely(!thread_spd->dlb_initialized)) {
244 return DLB_ERR_NOINIT;
245 }
246 3 return acquire_cpu(thread_spd, cpuid);
247 }
248
249 DLB_EXPORT_SYMBOL
250 13 int DLB_AcquireCpus(int ncpus) {
251 13 spd_enter_dlb(thread_spd);
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (unlikely(!thread_spd->dlb_initialized)) {
253 return DLB_ERR_NOINIT;
254 }
255 13 return acquire_cpus(thread_spd, ncpus);
256 }
257
258 DLB_EXPORT_SYMBOL
259 2 int DLB_AcquireCpuMask(const_dlb_cpu_set_t mask) {
260 2 spd_enter_dlb(thread_spd);
261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
262 return DLB_ERR_NOINIT;
263 }
264 2 return acquire_cpu_mask(thread_spd, mask);
265 }
266
267 DLB_EXPORT_SYMBOL
268 9 int DLB_AcquireCpusInMask(int ncpus, const_dlb_cpu_set_t mask) {
269 9 spd_enter_dlb(thread_spd);
270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (unlikely(!thread_spd->dlb_initialized)) {
271 return DLB_ERR_NOINIT;
272 }
273 9 return acquire_cpus_in_mask(thread_spd, ncpus, mask);
274 }
275
276
277 /* Borrow */
278
279 DLB_EXPORT_SYMBOL
280 2 int DLB_Borrow(void) {
281 2 spd_enter_dlb(thread_spd);
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
283 return DLB_ERR_NOINIT;
284 }
285 2 return borrow(thread_spd);
286 }
287
288 DLB_EXPORT_SYMBOL
289 2 int DLB_BorrowCpu(int cpuid) {
290 2 spd_enter_dlb(thread_spd);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
292 return DLB_ERR_NOINIT;
293 }
294 2 return borrow_cpu(thread_spd, cpuid);
295 }
296
297 DLB_EXPORT_SYMBOL
298 2 int DLB_BorrowCpus(int ncpus) {
299 2 spd_enter_dlb(thread_spd);
300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
301 return DLB_ERR_NOINIT;
302 }
303 2 return borrow_cpus(thread_spd, ncpus);
304 }
305
306 DLB_EXPORT_SYMBOL
307 2 int DLB_BorrowCpuMask(const_dlb_cpu_set_t mask) {
308 2 spd_enter_dlb(thread_spd);
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
310 return DLB_ERR_NOINIT;
311 }
312 2 return borrow_cpu_mask(thread_spd, mask);
313 }
314
315 DLB_EXPORT_SYMBOL
316 2 int DLB_BorrowCpusInMask(int ncpus, const_dlb_cpu_set_t mask) {
317 2 spd_enter_dlb(thread_spd);
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
319 return DLB_ERR_NOINIT;
320 }
321 2 return borrow_cpus_in_mask(thread_spd, ncpus, mask);
322 }
323
324
325 /* Return */
326
327 DLB_EXPORT_SYMBOL
328 2 int DLB_Return(void) {
329 2 spd_enter_dlb(thread_spd);
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
331 return DLB_ERR_NOINIT;
332 }
333 2 return return_all(thread_spd);
334 }
335
336 DLB_EXPORT_SYMBOL
337 8 int DLB_ReturnCpu(int cpuid) {
338 8 spd_enter_dlb(thread_spd);
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (unlikely(!thread_spd->dlb_initialized)) {
340 return DLB_ERR_NOINIT;
341 }
342 8 return return_cpu(thread_spd, cpuid);
343 }
344
345 DLB_EXPORT_SYMBOL
346 2 int DLB_ReturnCpuMask(const_dlb_cpu_set_t mask) {
347 2 spd_enter_dlb(thread_spd);
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (unlikely(!thread_spd->dlb_initialized)) {
349 return DLB_ERR_NOINIT;
350 }
351 2 return return_cpu_mask(thread_spd, mask);
352 }
353
354
355 /* DROM Responsive */
356
357 DLB_EXPORT_SYMBOL
358 4 int DLB_PollDROM(int *ncpus, dlb_cpu_set_t mask) {
359 4 spd_enter_dlb(thread_spd);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (unlikely(!thread_spd->dlb_initialized)) {
361 return DLB_ERR_NOINIT;
362 }
363 4 return poll_drom(thread_spd, ncpus, mask);
364 }
365
366 DLB_EXPORT_SYMBOL
367 3 int DLB_PollDROM_Update(void) {
368 3 spd_enter_dlb(thread_spd);
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (unlikely(!thread_spd->dlb_initialized)) {
370 return DLB_ERR_NOINIT;
371 }
372 3 return poll_drom_update(thread_spd);
373 }
374
375
376 /* Misc */
377
378 DLB_EXPORT_SYMBOL
379 17 int DLB_CheckCpuAvailability(int cpuid) {
380 17 spd_enter_dlb(thread_spd);
381 17 return check_cpu_availability(thread_spd, cpuid);
382 }
383
384 DLB_EXPORT_SYMBOL
385 7 int DLB_Barrier(void) {
386 7 spd_enter_dlb(thread_spd);
387 7 return node_barrier(thread_spd, NULL);
388 }
389
390 DLB_EXPORT_SYMBOL
391 5 int DLB_BarrierAttach(void) {
392 5 spd_enter_dlb(thread_spd);
393 5 return node_barrier_attach(thread_spd, NULL);
394 }
395
396 DLB_EXPORT_SYMBOL
397 9 int DLB_BarrierDetach(void) {
398 9 spd_enter_dlb(thread_spd);
399 9 return node_barrier_detach(thread_spd, NULL);
400 }
401
402 DLB_EXPORT_SYMBOL
403 dlb_barrier_t* DLB_BarrierNamedRegister(const char *barrier_name,
404 dlb_barrier_flags_t flags) {
405 spd_enter_dlb(thread_spd);
406 return (dlb_barrier_t*)node_barrier_register(thread_spd, barrier_name, flags);
407 }
408
409 DLB_EXPORT_SYMBOL
410 DLB_ALIAS(dlb_barrier_t*, DLB_BarrierNamedGet, \
411 (const char *barrier_name, dlb_barrier_flags_t flags), \
412 (barrier_name, flags), \
413 DLB_BarrierNamedRegister)
414
415 DLB_EXPORT_SYMBOL
416 int DLB_BarrierNamed(dlb_barrier_t *barrier) {
417 spd_enter_dlb(thread_spd);
418 return node_barrier(thread_spd, (barrier_t*)barrier);
419 }
420
421 DLB_EXPORT_SYMBOL
422 int DLB_BarrierNamedAttach(dlb_barrier_t *barrier) {
423 spd_enter_dlb(thread_spd);
424 return node_barrier_attach(thread_spd, (barrier_t*)barrier);
425 }
426
427 DLB_EXPORT_SYMBOL
428 int DLB_BarrierNamedDetach(dlb_barrier_t *barrier) {
429 spd_enter_dlb(thread_spd);
430 return node_barrier_detach(thread_spd, (barrier_t*)barrier);
431 }
432
433 DLB_EXPORT_SYMBOL
434 2 int DLB_SetVariable(const char *variable, const char *value) {
435 2 spd_enter_dlb(thread_spd);
436 2 return options_set_variable(&thread_spd->options, variable, value);
437 }
438
439 DLB_EXPORT_SYMBOL
440 3 int DLB_GetVariable(const char *variable, char *value) {
441 3 spd_enter_dlb(thread_spd);
442 3 return options_get_variable(&thread_spd->options, variable, value);
443 }
444
445 DLB_EXPORT_SYMBOL
446 1 int DLB_PrintVariables(int print_extended) {
447
448 1 spd_enter_dlb(thread_spd);
449
450
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (thread_spd->dlb_initialized) {
451 /* DLB has been previously initialized, use current options */
452 1 options_print_variables(&thread_spd->options, print_extended);
453 } else {
454 /* Parse DLB_ARGS and/or print defaults */
455 print_dlb_variables(thread_spd, print_extended);
456 }
457
458 1 return DLB_SUCCESS;
459 }
460
461 DLB_EXPORT_SYMBOL
462 5 int DLB_PrintShmem(int num_columns, dlb_printshmem_flags_t print_flags) {
463 5 spd_enter_dlb(thread_spd);
464 5 return print_shmem(thread_spd, num_columns, print_flags);
465 }
466
467 DLB_EXPORT_SYMBOL
468 1 const char* DLB_Strerror(int errnum) {
469 1 return error_get_str(errnum);
470 }
471
472 DLB_EXPORT_SYMBOL
473 2 int DLB_SetObserverRole(bool is_observer) {
474 2 spd_enter_dlb(thread_spd);
475 2 thread_ctx_set_observer(is_observer);
476 2 return DLB_SUCCESS;
477 }
478
479 DLB_EXPORT_SYMBOL
480 1 int DLB_GetVersion(int *major, int *minor, int *patch) {
481
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (major) *major = DLB_VERSION_MAJOR;
482
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (minor) *minor = DLB_VERSION_MINOR;
483
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (patch) *patch = DLB_VERSION_PATCH;
484 1 return DLB_SUCCESS;
485 }
486
487 DLB_EXPORT_SYMBOL
488 int DLB_GetGPUAffinity(char *buffer, size_t buffer_size, bool full_uuid) {
489 spd_enter_dlb(thread_spd);
490 return get_gpu_affinity(buffer, buffer_size, full_uuid);
491 }
492