GCC Code Coverage Report


Directory: src/
File: src/LB_comm/shmem_mngo.c
Date: 2026-09-15 07:37:49
Exec Total Coverage
Lines: 226 299 75.6%
Functions: 22 30 73.3%
Branches: 64 98 65.3%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2023 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 #include "LB_comm/shmem.h"
21 #include "LB_comm/shmem_mngo.h"
22 #include "LB_comm/shmem_procinfo.h"
23 #include "support/dlb_common.h"
24 #include "support/types.h"
25 #include <pthread.h>
26 #include <sched.h>
27 #include <stddef.h>
28
29 #ifdef MPI_LIB
30 #include "mpi/mpi_core.h"
31 #endif
32
33 #include "support/debug.h"
34 #include "support/mask_utils.h"
35
36 #include "apis/dlb_errors.h"
37
38 #include <stdio.h>
39 #include <string.h>
40
41 static int _mngo_test_barrier_participants = -1;
42
43 /**
44 * The struct containing the message if any of a manager.
45 */
46 typedef struct {
47 pid_t pid;
48 int rank;
49
50 // For the ACTIONS all2all
51 mngo_actions_t actions;
52
53 // For the DROM all2all's
54 int drom_core_change;
55 int dcores;
56 int ncores;
57 } mngo_manager_info_t;
58
59 /**
60 * The data structure of the MNGO shared memory.
61 */
62 typedef struct {
63 int attached;
64 pthread_barrier_t barrier;
65 pthread_mutex_t manager_lock;
66 pthread_cond_t manager_cond;
67 bool stop;
68 pthread_mutex_t stop_lock;
69 cpu_set_t available_cpus;
70 mngo_manager_info_t manager_info[0];
71 } shdata_t ;
72
73 /**
74 * The pointer to the data structure used by MNGO for the communication among
75 * the different manager threads.
76 */
77 static shdata_t *shdata = NULL;
78
79 /**
80 * The pointer to the shm handler to interact with the shmem interface.
81 */
82 static shmem_handler_t *shm_handler = NULL;
83
84 /**
85 * The maximum of sub processes that can be atached to the shared memory.
86 */
87 static size_t max_attached;
88
89 /**
90 * The amount of sub processes atached to the shared memory.
91 */
92 static size_t subprocesses_attached;
93
94 /**
95 * The shared memory name. Used to identify shared memory files for the MNGo module.
96 */
97 static const char *shmem_name = "mngo";
98
99 /**
100 * Process wide pthread mutex.
101 */
102 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
103
104 17 static void close_shmem(void) {
105 17 pthread_mutex_lock(&mutex);
106 17 subprocesses_attached--;
107
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
17 if (subprocesses_attached == 0) {
108 15 shmem_finalize(shm_handler, NULL /* do not check if empty */);
109 }
110 17 pthread_mutex_unlock(&mutex);
111 17 }
112
113 15 static int shmem_mngo_size(void) {
114 15 return sizeof(shdata_t) + sizeof(mngo_manager_info_t) * max_attached;
115 }
116
117 8 static void shmem_mngo_barrier_init(int participants) {
118 pthread_barrierattr_t attr;
119 8 pthread_barrierattr_init(&attr);
120 8 pthread_barrierattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
121 8 pthread_barrier_init(&shdata->barrier, &attr, participants);
122 8 pthread_barrierattr_destroy(&attr);
123 8 }
124
125 16 static void shmem_mngo_lock_init(pthread_mutex_t * lock) {
126 pthread_mutexattr_t attr;
127 16 pthread_mutexattr_init(&attr);
128 16 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
129 16 pthread_mutex_init(lock, &attr);
130 16 pthread_mutexattr_destroy(&attr);
131 16 }
132
133 8 static void shmem_mngo_manager_cond_init(void) {
134 pthread_condattr_t attr;
135 8 pthread_condattr_init(&attr);
136 8 pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
137 8 pthread_cond_init(&shdata->manager_cond, &attr);
138 8 pthread_condattr_destroy(&attr);
139 8 }
140
141
142 /* This function may be called from shmem_init to cleanup pid */
143 static void cleanup_shmem(void *shdata_ptr, int pid) {
144 bool shmem_empty = true;
145 shdata_t *shared_data = shdata_ptr;
146 size_t id;
147 for (id = 0; id < max_attached; id++) {
148 if (shared_data->manager_info[id].pid == pid) {
149 memset(&shdata->manager_info[id], 0, sizeof(mngo_manager_info_t));
150 break;
151 } else if (shared_data->manager_info[id].pid > 0) {
152 shmem_empty = false;
153 }
154 }
155
156 /* If there are no registered processes, make sure shmem is reset */
157 if (shmem_empty) {
158 memset(shared_data, 0, shmem_mngo_size());
159 }
160 }
161
162 17 int shmem_mngo_init(const char *shmem_key, pid_t pid, int rank, size_t *mid) {
163
164 17 int error = DLB_ERR_UNKNOWN;
165
166 #ifdef MPI_LIB
167 int barrier_participants = _mpis_per_node;
168 #else
169 17 int barrier_participants = 1;
170 #endif
171
172
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (unlikely(_mngo_test_barrier_participants > -1)) {
173 10 barrier_participants = _mngo_test_barrier_participants;
174 }
175
176 17 pthread_mutex_lock(&mutex);
177 {
178
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
17 if (shm_handler == NULL) {
179 15 max_attached = mu_get_system_size();
180 30 shm_handler = shmem_init((void**)&shdata,
181 30 &(const shmem_props_t) {
182 15 .size = shmem_mngo_size(),
183 .name = shmem_name,
184 .key = shmem_key,
185 .version = SHMEM_VERSION_IGNORE,
186 .cleanup_fn = cleanup_shmem,
187 });
188 15 subprocesses_attached = 1;
189 } else {
190 2 subprocesses_attached++;
191 }
192 }
193 17 pthread_mutex_unlock(&mutex);
194
195 size_t id;
196 17 shmem_lock(shm_handler);
197 {
198 /* If it is the first process to access this the whole shm will be 0 */
199
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1 times.
27 for (id = 0; id < max_attached; id++) {
200
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 10 times.
26 if (! shdata->manager_info[id].pid) {
201 16 shdata->manager_info[id].pid = pid;
202 16 shdata->manager_info[id].rank = rank;
203 16 error = DLB_SUCCESS;
204 16 break;
205 }
206 }
207
208
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9 times.
17 if (id == 0) {
209 8 shmem_mngo_barrier_init(barrier_participants);
210 8 shmem_mngo_lock_init(&shdata->manager_lock);
211 8 shmem_mngo_lock_init(&shdata->stop_lock);
212 8 shmem_mngo_manager_cond_init();
213 }
214
215 17 shdata->attached++;
216 }
217 17 shmem_unlock(shm_handler);
218
219
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16 times.
17 if (id == max_attached) {
220 1 error = DLB_ERR_NOSHMEM;
221 }
222
223
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16 times.
17 if (error != DLB_SUCCESS) {
224 1 close_shmem();
225 1 warn_error(error);
226 }
227
228 17 *mid = id;
229
230 17 return error;
231 }
232
233 static void shmem_mngo_ext__init(const char *shmem_key) {
234 max_attached = mu_get_system_size();
235 shm_handler = shmem_init((void**)&shdata,
236 &(const shmem_props_t) {
237 .size = shmem_mngo_size(),
238 .name = shmem_name,
239 .key = shmem_key,
240 .version = SHMEM_VERSION_IGNORE,
241 });
242 }
243
244 16 int shmem_mngo_fini(size_t mid) {
245 bool was_active;
246 16 shmem_lock(shm_handler);
247 {
248 16 was_active = shdata->manager_info[mid].pid != 0;
249 16 shdata->manager_info[mid].pid = 0;
250 }
251 16 shmem_unlock(shm_handler);
252
253
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (was_active) {
254 16 close_shmem();
255 }
256
257 16 return DLB_SUCCESS;
258 }
259
260 14 void shmem_mngo_fini_sync(void) {
261 14 shmem_lock(shm_handler);
262 {
263 14 shdata->attached--;
264 }
265 14 shmem_unlock(shm_handler);
266 11 while (1) {
267 int num_attached;
268 25 shmem_mngo_barrier_wait();
269 25 shmem_lock(shm_handler);
270 {
271 25 num_attached = shdata->attached;
272 }
273 25 shmem_unlock(shm_handler);
274
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11 times.
25 if (num_attached == 0) break;
275 }
276 14 }
277
278 static int shmem_mngo_ext__finalize(void) {
279 // Protect double finalization
280 if (shm_handler == NULL) {
281 return DLB_ERR_NOSHMEM;
282 }
283
284 // Shared memory destruction
285 shmem_finalize(shm_handler, NULL /* do not check if empty */);
286 shm_handler = NULL;
287 shdata = NULL;
288
289 return DLB_SUCCESS;
290 }
291
292 32 static int assert_manager_active(const size_t mid) {
293
294 32 int error = DLB_SUCCESS;
295
296
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if (mid > max_attached || !shdata->manager_info[mid].pid) {
297 error = DLB_ERR_UNKNOWN;
298 }
299
300 32 return error;
301 }
302
303 161 void shmem_mngo_barrier_wait(void) {
304 161 pthread_barrier_wait(&shdata->barrier);
305 161 }
306
307 // not thread-safe, this function should be guarded with a shdata->stop_lock
308 7 void shmem_mngo_set_stop_flag(bool flag) {
309 7 shmem_lock(shm_handler);
310 7 shdata->stop = flag;
311 7 shmem_unlock(shm_handler);
312 7 }
313
314 bool shmem_mngo_check_stop_flag(void) {
315 shmem_lock(shm_handler);
316 bool stop = shdata->stop;
317 shmem_unlock(shm_handler);
318
319 return stop;
320 }
321
322 void shmem_mngo_manager_wake(void) {
323 // Aquire the lock.
324 pthread_mutex_lock(&shdata->manager_lock);
325
326 // Wake up the manager thread via the pthread cond.
327 pthread_cond_signal(&shdata->manager_cond);
328
329 // Imediatly release the lock.
330 pthread_mutex_unlock(&shdata->manager_lock);
331 }
332
333 7 void shmem_mngo_manager_wake_finalize(void) {
334 // The only moment we can aquire both locks is when shmem_mngo_manager_wait
335 // is wating in the `pthread_cond_wait`
336 7 pthread_mutex_lock(&shdata->stop_lock);
337 7 pthread_mutex_lock(&shdata->manager_lock);
338
339 // Set the finalize flag
340 7 shmem_mngo_set_stop_flag(true);
341
342 // Wake up the manager thread via the pthread cond.
343 7 pthread_cond_broadcast(&shdata->manager_cond);
344
345 // Imediatly release the lock.
346 7 pthread_mutex_unlock(&shdata->manager_lock);
347 7 pthread_mutex_unlock(&shdata->stop_lock);
348 7 }
349
350 void shmem_mngo_manager_wait(const struct timespec *abstime) {
351
352 // Release the lock while I am asleep
353 pthread_mutex_lock(&shdata->manager_lock);
354 pthread_mutex_unlock(&shdata->stop_lock);
355
356 // Waits for the condition to be fullfiled for abstime seconds, after either of
357 // both conditions is fullfiled the lock is aquired when possible to continue.
358 pthread_cond_timedwait(&shdata->manager_cond, &shdata->manager_lock, abstime);
359
360 // Aquire the lock when I wake up
361 pthread_mutex_lock(&shdata->stop_lock);
362 pthread_mutex_unlock(&shdata->manager_lock);
363 }
364
365 44 pid_t shmem_mngo_get_pid(const size_t mid) {
366 44 return shdata->manager_info[mid].pid;
367 }
368
369 size_t shmem_mngo_get_max_size(void) {
370 return max_attached;
371 }
372
373 12 void shmem_mngo__alltoall_actions(size_t mid, mngo_actions_t *actions) {
374 12 int error = assert_manager_active(mid);
375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (error != DLB_SUCCESS) {
376 fatal("Trying to use the MNGO shared memory while uninitialized, at %s", __func__);
377 }
378
379 12 shmem_lock(shm_handler);
380 {
381 12 shdata->manager_info[mid].actions = *actions;
382 }
383 12 shmem_unlock(shm_handler);
384
385 12 shmem_mngo_barrier_wait();
386
387 12 mngo_actions_t result = MNGO_ACTION_NONE;
388 // Collect the results
389
2/2
✓ Branch 0 taken 1536 times.
✓ Branch 1 taken 12 times.
1548 for (size_t i = 0; i < max_attached; i++) {
390 1536 mngo_manager_info_t *info = &shdata->manager_info[i];
391
2/2
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 24 times.
1536 if (info->pid == 0) continue;
392 24 result = result > info->actions ? result : info->actions;
393 }
394
395 12 *actions = result;
396 12 }
397
398 10 int shmem_mngo_drom__alltoall_deltas_start(size_t mid, int self_cpu_delta) {
399 10 int error = assert_manager_active(mid);
400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (error != DLB_SUCCESS) {
401 fatal("Trying to use the MNGO shared memory while uninitialized, at %s", __func__);
402 }
403
404 // Share self intention
405 10 shmem_lock(shm_handler);
406 {
407 10 shdata->manager_info[mid].drom_core_change = self_cpu_delta;
408 }
409 10 shmem_unlock(shm_handler);
410
411 10 shmem_mngo_barrier_wait();
412
413 10 return max_attached;
414 }
415
416 10 void shmem_mngo_drom__alltoall_deltas_finish(size_t mid, int *cpu_deltas) {
417 // Collect the results
418
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 10 times.
794 for (size_t i = 0; i < max_attached; i++) {
419
2/2
✓ Branch 0 taken 764 times.
✓ Branch 1 taken 20 times.
784 if (shdata->manager_info[i].pid == 0) {
420 764 cpu_deltas[i] = 0;
421 } else {
422 20 cpu_deltas[i] = shdata->manager_info[i].drom_core_change;
423 }
424 }
425
426 10 shmem_mngo_barrier_wait();
427
428 // Clean up axiliar variables in shared memory
429
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (mid == 0) {
430 5 shmem_lock(shm_handler);
431 {
432
2/2
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 5 times.
397 for (unsigned int id = 0; id < max_attached; id++) {
433 392 shdata->manager_info[id].drom_core_change = 0;
434 }
435 }
436 5 shmem_unlock(shm_handler);
437 }
438
439 10 shmem_mngo_barrier_wait();
440 10 }
441
442 static char * shmem_mngo_print_redistribution_val = NULL;
443
444 10 void shmem_mngo_drom__print_redistribution(int mid, int dcores, const char* region_name) {
445 10 pid_t pid = shmem_mngo_get_pid(mid);
446
447 cpu_set_t mask;
448 10 shmem_procinfo__getprocessmask(pid, &mask, DLB_DROM_FLAGS_NONE);
449
450 10 shmem_mngo_barrier_wait();
451 {
452 10 shdata->manager_info[mid].dcores = dcores;
453 10 shdata->manager_info[mid].ncores = mu_count_cores_intersecting_with_cpuset(&mask);
454 }
455 10 shmem_mngo_barrier_wait();
456
457
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (mid == 0) {
458 // TODO: Move to shmem_mngo_init
459
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (shmem_mngo_print_redistribution_val == NULL) {
460 3 shmem_mngo_print_redistribution_val = malloc(sizeof(char) * 512);
461 }
462
463 5 char *buff = shmem_mngo_print_redistribution_val;
464
465 5 shmem_lock(shm_handler);
466 {
467 int i;
468 5 int size = 0;
469
470 5 bool changed = false;
471 5 int max_ncores = 0;
472 5 int max_rank = 0;
473
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for ( i = 0; i < shdata->attached; i++) {
474 10 int curr_ncores = shdata->manager_info[i].ncores;
475 10 max_ncores = curr_ncores > max_ncores ? curr_ncores : max_ncores;
476
477 10 int curr_dcores = shdata->manager_info[i].dcores;
478 10 changed |= curr_dcores != 0;
479
480 10 int curr_rank = shdata->manager_info[i].rank;
481 10 max_rank = curr_rank > max_rank ? curr_rank : max_rank;
482 }
483
484
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (changed) {
485 static const char *format = " [ %*d: %*d (%+*d) ] ";
486
487 2 int digits_rank = snprintf(NULL, 0, "%d", max_rank);
488 2 int digits_cores = snprintf(NULL, 0, "%d", max_ncores);
489 2 int col_size = snprintf(NULL, 0, format,
490 digits_rank, 0,
491 digits_cores, 0,
492 digits_cores, 0);
493
494 2 int num_cols = 80 / col_size;
495 2 int line_width = num_cols * col_size;
496
497
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (i = 0; i < shdata->attached; i++) {
498
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (i % num_cols == 0) size += snprintf(&buff[size], 512 - size, "\n");
499
500 4 size += snprintf(&buff[size], 512 - size, format,
501 4 digits_rank, shdata->manager_info[i].rank,
502 4 digits_cores, shdata->manager_info[i].ncores,
503 4 digits_cores, shdata->manager_info[i].dcores);
504 }
505
506 static const char title[] = "MNGO REDISTRIBUTION REPORT [ rank: #cores (#change) ]";
507 static const int title_len = sizeof(title) - 1; // -1 the null terminator
508
509 2 info("Region: %s\n%*s%*s%s\n", region_name,
510 2 line_width/2+title_len/2, title, line_width/2-title_len/2, "", // Center the title
511 shmem_mngo_print_redistribution_val);
512 }
513 }
514 5 shmem_unlock(shm_handler);
515 }
516 10 }
517
518 // This function redistribues the Cores among processes acording to the data in
519 // <actions>
520 //
521 // Invariant:
522 // - All the MNGO managers of the same node must call the routine.
523 // - actions->self_drom_core_change of all MNGO managers must add up to 0
524 10 void shmem_mngo_drom__redistribute(size_t mid, int cpu_delta, cpu_set_t *self_mask) {
525
526 10 int error = assert_manager_active(mid);
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (error != DLB_SUCCESS) {
528 fatal("Trying to use the MNGO shared memory while uninitialized, at %s", __func__);
529 }
530
531 10 pid_t pid = shmem_mngo_get_pid(mid);
532 10 shmem_procinfo__getprocessmask(pid, self_mask, DLB_DROM_FLAGS_NONE);
533
534 // Handle the case where the number of resources of this process has to be
535 // reduced (namely, "giving" processes) by removing Cores from the process
536 // mask.
537
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (cpu_delta < 0) {
538 cpu_set_t mask_freed;
539 2 CPU_ZERO(&mask_freed);
540
541 // Release as many cores as self_crom_core_change, and add them in a local free mask
542 int released_cores;
543 2 for(released_cores = 0;
544
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 2 times.
90 released_cores < -cpu_delta;
545 88 released_cores++) {
546
547 cpu_set_t mask_release_cpu;
548
549 88 int release_cpu = mu_get_last_cpu(self_mask);
550 // When there are CPUs available
551
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if ( release_cpu >= 0 ) {
552 // Get the set CPUs that are in the same core as "release_cpu" and also in maks_ptr
553 88 mu_and(&mask_release_cpu, self_mask, mu_get_core_mask(release_cpu)->set);
554 // Remove those CPUs from mask_ptr
555 88 mu_subtract(self_mask, self_mask, &mask_release_cpu);
556 // Add them into mask_freed
557 88 mu_or(&mask_freed, &mask_freed, &mask_release_cpu);
558 } else {
559 // Something bad happened and we have released all cores.
560 fatal("accidentally released all cpus in this process. This is a bug :O");
561 }
562 }
563
564
565 // Update the MNGO free mask with the local free mask.
566 2 shmem_lock(shm_handler);
567 {
568
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 verbose(VB_MNGO, "SHMEM MNGO [%zu]: New Released %s",mid, mu_to_str(self_mask));
569
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 verbose(VB_MNGO, "SHMEM MNGO [%zu]: Freed %s",mid, mu_to_str(&mask_freed));
570 2 mu_or(&shdata->available_cpus, &shdata->available_cpus, &mask_freed);
571 }
572 2 shmem_unlock(shm_handler);
573 }
574
575 // Wait for all the processes to release the CPUs
576 10 shmem_mngo_barrier_wait();
577
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 verbose(VB_MNGO, "SHMEM MNGO [%zu]: Avail %s", mid, mu_to_str(&shdata->available_cpus));
578
579 // Handle the case where the number of resources of this process has to
580 // increase (namely, "receiving" processes) by adding CPUs previously freed
581 // by the "giving" processes.
582
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (cpu_delta > 0) {
583 2 shmem_lock(shm_handler);
584 {
585 2 cpu_set_t *mask_free = &shdata->available_cpus;
586
587 int num_aquired_cores;
588 2 for(num_aquired_cores = 0;
589
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 2 times.
90 num_aquired_cores < cpu_delta;
590 88 num_aquired_cores++) {
591 // Find the las CPU available in the mask_free
592 88 int cpu_to_aquire = mu_get_last_cpu(mask_free);
593 // When there are CPUs left
594
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if ( cpu_to_aquire >= 0 ) {
595 // Get the set of CPUs that are in the same core as
596 // "cpu_to_aquire" and also in maks_free.
597 cpu_set_t mask_core_to_aquire;
598 88 mu_and(&mask_core_to_aquire,
599 88 mask_free, mu_get_core_mask(cpu_to_aquire)->set);
600 // Remove those CPU from mask_free
601 88 mu_subtract(mask_free, mask_free, &mask_core_to_aquire);
602 // Add them into the process mask
603 88 mu_or(self_mask, self_mask, &mask_core_to_aquire);
604 } else {
605 // We are trying to aquire more cores than what was
606 // freed. No big deal just break.
607 warning("Trying to aquire more cpus than available");
608 break;
609 }
610 }
611
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 verbose(VB_MNGO, "SHMEM MNGO [%zu]: New Added %s",mid, mu_to_str(self_mask));
612 }
613 2 shmem_unlock(shm_handler);
614 }
615 10 }
616
617 5 void shmem_mngo__print_info(const char *shmem_key) {
618
619
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 if (! shmem_exists(shmem_name, shmem_key)) {
620 5 return;
621 }
622
623 /* If the shmem is not opened, obtain a temporary fd */
624 bool temporary_shmem = shm_handler == NULL;
625 if (temporary_shmem) {
626 shmem_mngo_ext__init(shmem_key);
627 }
628
629 /* Make a full copy of the shared memory */
630 shdata_t *shdata_copy = malloc(shmem_mngo_size());
631 shmem_lock(shm_handler);
632 {
633 memcpy(shdata_copy, shdata, shmem_mngo_size());
634 }
635 shmem_unlock(shm_handler);
636
637 /* Close shmem if needed */
638 if (temporary_shmem) {
639 shmem_mngo_ext__finalize();
640 }
641
642 /* Initialize buffer */
643 print_buffer_t buffer;
644 printbuffer_init(&buffer);
645
646 /* Set up line buffer */
647 enum { MAX_LINE_LEN = 128 };
648 char line[MAX_LINE_LEN];
649
650 size_t mid;
651 for (mid = 0; mid < max_attached; ++mid) {
652
653 if (shdata->manager_info[mid].pid) {
654 /* Append line to buffer */
655 snprintf(line, MAX_LINE_LEN,
656 "NOT IMPLEMENTED");
657 printbuffer_append(&buffer, line);
658 }
659 }
660
661
662 if (buffer.addr[0] != '\0' ) {
663 info0("=== MNGO ===\n"
664 " | %12s | %12s | %12s | %12s |\n"
665 "%s", "Manager ID", "Finalize", "LeWI", "DROM", buffer.addr);
666 }
667 printbuffer_destroy(&buffer);
668 free(shdata_copy);
669 shdata_copy = NULL;
670 }
671
672 /**
673 * Fork handlers
674 */
675 19 void shmem_mngo__atfork_prepare(void) {
676 19 pthread_mutex_lock(&mutex);
677 19 }
678
679 19 void shmem_mngo__atfork_parent(void) {
680 19 pthread_mutex_unlock(&mutex);
681 19 }
682
683 void shmem_mngo__atfork_child(void) {
684
685 pthread_mutex_init(&mutex, NULL);
686
687 if (shm_handler != NULL) {
688 shmem_detach_after_fork(shm_handler);
689 shdata = NULL;
690 shm_handler = NULL;
691 subprocesses_attached = 0;
692 }
693 }
694
695 /**
696 * Test functions
697 */
698 5 void test_shmem_mngo__modify_barrier_participants(int participants) {
699 5 _mngo_test_barrier_participants = participants;
700 5 }
701