GCC Code Coverage Report


Directory: src/
File: src/apis/DLB_interface.c
Date: 2025-11-21 10:34:40
Exec Total Coverage
Lines: 180 218 82.6%
Functions: 46 49 93.9%
Branches: 37 74 50.0%

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