GCC Code Coverage Report


Directory: src/
File: src/apis/DLB_interface.c
Date: 2026-04-21 15:16:03
Exec Total Coverage
Lines: 173 220 78.6%
Functions: 43 49 87.8%
Branches: 39 76 51.3%

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