GCC Code Coverage Report


Directory: src/
File: src/LB_comm/shmem_talp.c
Date: 2024-11-22 17:07:10
Exec Total Coverage
Lines: 207 235 88.1%
Functions: 21 22 95.5%
Branches: 105 134 78.4%

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 #include "LB_comm/shmem_talp.h"
21
22 #include "LB_comm/shmem.h"
23 #include "apis/dlb_errors.h"
24 #include "apis/dlb_talp.h"
25 #include "support/atomic.h"
26 #include "support/debug.h"
27 #include "support/types.h"
28 #include "support/mask_utils.h"
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <pthread.h>
33 #include <inttypes.h>
34
35
36 enum { NOBODY = 0 };
37 enum { DEFAULT_REGIONS_PER_PROC = 100 };
38
39
40 typedef struct DLB_ALIGN_CACHE talp_region_t {
41 char name[DLB_MONITOR_NAME_MAX];
42 atomic_int_least64_t mpi_time;
43 atomic_int_least64_t useful_time;
44 pid_t pid;
45 float avg_cpus;
46 } talp_region_t;
47
48 typedef struct {
49 bool initialized;
50 int max_regions;
51 talp_region_t talp_region[];
52 } shdata_t;
53
54 enum { SHMEM_TALP_VERSION = 3 };
55
56 static shmem_handler_t *shm_handler = NULL;
57 static shdata_t *shdata = NULL;
58 static int regions_per_proc_initialized = 0;
59 static const char *shmem_name = "talp";
60 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
61 static int subprocesses_attached = 0;
62
63
64 /*********************************************************************************/
65 /* Init / Finalize */
66 /*********************************************************************************/
67
68 /* This function may be called from shmem_init to cleanup pid */
69 static void cleanup_shmem(void *shdata_ptr, int pid) {
70 bool shmem_empty = true;
71 shdata_t *shared_data = shdata_ptr;
72 int region_id;
73 int max_regions = shared_data->max_regions;
74 for (region_id = 0; region_id < max_regions; ++region_id) {
75 talp_region_t *talp_region = &shared_data->talp_region[region_id];
76 if (talp_region->pid == pid) {
77 *talp_region = (const talp_region_t){};
78 } else if (talp_region->pid > 0) {
79 shmem_empty = false;
80 }
81 }
82
83 /* If there are no registered processes, make sure shmem is reset */
84 if (shmem_empty) {
85 memset(shared_data, 0, shmem_talp__size());
86 }
87 }
88
89 22 static bool is_shmem_empty(void) {
90 int region_id;
91 22 int max_regions = shdata->max_regions;
92
2/2
✓ Branch 0 taken 10409 times.
✓ Branch 1 taken 21 times.
10430 for (region_id = 0; region_id < max_regions; ++region_id) {
93
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10408 times.
10409 if (shdata->talp_region[region_id].pid != NOBODY) {
94 1 return false;
95 }
96 }
97 21 return true;
98 }
99
100 25 static void open_shmem(const char *shmem_key, int regions_per_process) {
101 25 pthread_mutex_lock(&mutex);
102 {
103
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3 times.
25 if (shm_handler == NULL) {
104 // Use either requested or default value
105 22 regions_per_proc_initialized = regions_per_process ?
106
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 regions_per_process : DEFAULT_REGIONS_PER_PROC;
107
108 44 shm_handler = shmem_init((void**)&shdata,
109 22 &(const shmem_props_t) {
110 22 .size = shmem_talp__size(),
111 .name = shmem_name,
112 .key = shmem_key,
113 .version = SHMEM_TALP_VERSION,
114 .cleanup_fn = cleanup_shmem,
115 });
116 22 subprocesses_attached = 1;
117 } else {
118 3 ++subprocesses_attached;
119 }
120 }
121 25 pthread_mutex_unlock(&mutex);
122 25 }
123
124 25 static void close_shmem(void) {
125 25 pthread_mutex_lock(&mutex);
126 {
127
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3 times.
25 if (--subprocesses_attached == 0) {
128 22 shmem_finalize(shm_handler, is_shmem_empty);
129 22 shm_handler = NULL;
130 22 shdata = NULL;
131 }
132 }
133 25 pthread_mutex_unlock(&mutex);
134 25 }
135
136 10 int shmem_talp__init(const char *shmem_key, int regions_per_process) {
137 10 int error = DLB_SUCCESS;
138
139 // Shared memory creation
140 10 open_shmem(shmem_key, regions_per_process);
141
142 10 shmem_lock(shm_handler);
143 {
144 // Initialize some values if this is the 1st process attached to the shmem
145
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (!shdata->initialized) {
146 8 shdata->initialized = true;
147 16 shdata->max_regions = mu_get_system_size() * (regions_per_process ?
148
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 regions_per_process : DEFAULT_REGIONS_PER_PROC);
149 } else {
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (regions_per_process != 0
151 && shdata->max_regions != regions_per_process * mu_get_system_size()) {
152 error = DLB_ERR_INIT;
153 }
154 }
155 }
156 10 shmem_unlock(shm_handler);
157
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (error == DLB_ERR_INIT) {
159 warning("Cannot initialize TALP shmem for %d regions per process, already"
160 " allocated for %d, accounting for %d processes. Check for DLB_ARGS"
161 " consistency among processes or clean up shared memory.",
162 regions_per_process, shdata->max_regions, mu_get_system_size());
163 }
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (error < DLB_SUCCESS) {
166 // The shared memory contents are untouched, but the counter needs to
167 // be decremented, and the shared memory deleted if needed
168 close_shmem();
169 }
170
171 10 return error;
172 }
173
174 15 int shmem_talp_ext__init(const char *shmem_key, int regions_per_process) {
175 // Shared memory creation
176 15 open_shmem(shmem_key, regions_per_process);
177
178 // External processes don't need to initialize anything
179
180 15 return DLB_SUCCESS;
181 }
182
183 11 int shmem_talp__finalize(pid_t pid) {
184 11 int error = DLB_SUCCESS;
185
186
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (shm_handler == NULL) {
187 1 return DLB_ERR_NOSHMEM;
188 }
189
190 // Remove all regions associated with pid
191 10 shmem_lock(shm_handler);
192 {
193 int region_id;
194 10 int max_regions = shdata->max_regions;
195
2/2
✓ Branch 0 taken 16008 times.
✓ Branch 1 taken 10 times.
16018 for (region_id = 0; region_id < max_regions; ++region_id) {
196 16008 talp_region_t *talp_region = &shdata->talp_region[region_id];
197
2/2
✓ Branch 0 taken 810 times.
✓ Branch 1 taken 15198 times.
16008 if (talp_region->pid == pid) {
198 810 *talp_region = (const talp_region_t){};
199 }
200 }
201 }
202 10 shmem_unlock(shm_handler);
203
204 // Close shared memory
205 10 close_shmem();
206
207 10 return error;
208 }
209
210 15 int shmem_talp_ext__finalize(void) {
211 // Protect double finalization
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (shm_handler == NULL) {
213 return DLB_ERR_NOSHMEM;
214 }
215
216 // Shared memory destruction
217 15 close_shmem();
218
219 15 return DLB_SUCCESS;
220 }
221
222
223 /*********************************************************************************/
224 /* Register regions */
225 /*********************************************************************************/
226
227 /* Register monitoring region with name "name", or look up if already registered.
228 * Return associated node-unique id by parameter. */
229 812 int shmem_talp__register(pid_t pid, float avg_cpus, const char *name, int *node_shared_id) {
230
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 811 times.
812 if (shm_handler == NULL) return DLB_ERR_NOSHMEM;
231
232 int error;
233 811 shmem_lock(shm_handler);
234 {
235 /* Iterate until region is found, find an empty spot in the same pass */
236 811 talp_region_t *empty_spot = NULL;
237 811 int found_id = -1;
238 int region_id;
239 811 int max_regions = shdata->max_regions;
240
2/2
✓ Branch 0 taken 662408 times.
✓ Branch 1 taken 811 times.
663219 for (region_id = 0; region_id < max_regions; ++region_id) {
241 662408 talp_region_t *talp_region = &shdata->talp_region[region_id];
242
2/2
✓ Branch 0 taken 321214 times.
✓ Branch 1 taken 341194 times.
662408 if (empty_spot == NULL
243
2/2
✓ Branch 0 taken 810 times.
✓ Branch 1 taken 320404 times.
321214 && talp_region->pid == NOBODY) {
244 /* First empty spot */
245 810 empty_spot = talp_region;
246 810 found_id = region_id;
247 }
248
2/2
✓ Branch 0 taken 319602 times.
✓ Branch 1 taken 341996 times.
661598 else if (talp_region->pid == pid
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 319602 times.
319602 && strncmp(talp_region->name, name, DLB_MONITOR_NAME_MAX-1) == 0) {
250 /* Region was already registered */
251 found_id = region_id;
252 break;
253 }
254 }
255
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 811 times.
811 if (found_id == region_id) {
257 /* Already registered */
258 *node_shared_id = found_id;
259 error = DLB_NOUPDT;
260
3/4
✓ Branch 0 taken 811 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 810 times.
✓ Branch 3 taken 1 times.
811 } else if (region_id == max_regions && empty_spot != NULL) {
261 /* Register new region */
262 810 *empty_spot = (const talp_region_t) {.pid = pid, .avg_cpus = avg_cpus};
263 810 snprintf(empty_spot->name, DLB_MONITOR_NAME_MAX, "%s", name);
264 810 *node_shared_id = found_id;
265 810 error = DLB_SUCCESS;
266 } else {
267 /* No mem left */
268 1 error = DLB_ERR_NOMEM;
269 }
270 }
271 811 shmem_unlock(shm_handler);
272
273 811 return error;
274 }
275
276 /*********************************************************************************/
277 /* Getters */
278 /*********************************************************************************/
279
280 /* Obtain a list of PIDs that have registered a region */
281 2 int shmem_talp__get_pidlist(pid_t *pidlist, int *nelems, int max_len) {
282
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (shm_handler == NULL) return DLB_ERR_NOSHMEM;
283
284 1 *nelems = 0;
285 1 shmem_lock(shm_handler);
286 {
287 int region_id;
288 1 int max_regions = shdata->max_regions;
289
3/4
✓ Branch 0 taken 800 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 800 times.
✗ Branch 3 not taken.
801 for (region_id = 0; region_id < max_regions && *nelems < max_len; ++region_id) {
290 800 pid_t pid = shdata->talp_region[region_id].pid;
291
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 797 times.
800 if (pid != NOBODY) {
292 // pid is valid, check if already in pidlist
293 int i;
294
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (i=0; i<(*nelems); ++i) {
295
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (pid == pidlist[i])
296 1 break;
297 }
298 // add if not found
299
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (i == *nelems) {
300 2 pidlist[(*nelems)++] = pid;
301 }
302 }
303 }
304 }
305 1 shmem_unlock(shm_handler);
306 1 return DLB_SUCCESS;
307 }
308
309 4 static int cmp_region_list(const void *elem1, const void *elem2) {
310 4 return ((talp_region_list_t*)elem1)->pid - ((talp_region_list_t*)elem2)->pid;
311 }
312
313 /* Look up for a registered monitoring region with the given "name" and "pid". */
314 5 int shmem_talp__get_region(talp_region_list_t *region, pid_t pid, const char *name) {
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (shm_handler == NULL) return DLB_ERR_NOSHMEM;
316
317 5 int error = DLB_ERR_NOPROC;
318 5 shmem_lock(shm_handler);
319 {
320 int region_id;
321 5 int max_regions = shdata->max_regions;
322
2/2
✓ Branch 0 taken 803 times.
✓ Branch 1 taken 2 times.
805 for (region_id = 0; region_id < max_regions; ++region_id) {
323 803 talp_region_t *talp_region = &shdata->talp_region[region_id];
324
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 800 times.
803 if (talp_region->pid == pid
325
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 && strncmp(talp_region->name, name, DLB_MONITOR_NAME_MAX-1) == 0) {
326 3 *region = (const talp_region_list_t) {
327 .pid = pid,
328 .region_id = region_id,
329 3 .mpi_time = DLB_ATOMIC_LD_RLX(&talp_region->mpi_time),
330 3 .useful_time = DLB_ATOMIC_LD_RLX(&talp_region->useful_time),
331 3 .avg_cpus = talp_region->avg_cpus,
332 };
333 3 error = DLB_SUCCESS;
334 3 break;
335 }
336 }
337 }
338 5 shmem_unlock(shm_handler);
339
340 5 return error;
341 }
342
343 /* Obtain a list of regions for a given name, sorted by PID */
344 12 int shmem_talp__get_regionlist(talp_region_list_t *region_list, int *nelems,
345 int max_len, const char *name) {
346
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 if (shm_handler == NULL) return DLB_ERR_NOSHMEM;
347
348 11 *nelems = 0;
349 11 shmem_lock(shm_handler);
350 {
351 int region_id;
352 11 int max_regions = shdata->max_regions;
353
4/4
✓ Branch 0 taken 4013 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 4011 times.
✓ Branch 3 taken 2 times.
4022 for (region_id = 0; region_id < max_regions && *nelems < max_len; ++region_id) {
354 4011 talp_region_t *talp_region = &shdata->talp_region[region_id];
355
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 3991 times.
4011 if (talp_region->pid != NOBODY
356
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
20 && strncmp(talp_region->name, name, DLB_MONITOR_NAME_MAX-1) == 0) {
357 14 region_list[(*nelems)++] = (const talp_region_list_t) {
358 14 .pid = talp_region->pid,
359 .region_id = region_id,
360 14 .mpi_time = DLB_ATOMIC_LD_RLX(&talp_region->mpi_time),
361 14 .useful_time = DLB_ATOMIC_LD_RLX(&talp_region->useful_time),
362 14 .avg_cpus = talp_region->avg_cpus,
363 };
364 }
365 }
366 }
367 11 shmem_unlock(shm_handler);
368
369 /* Sort array by PID */
370 11 qsort(region_list, *nelems, sizeof(talp_region_list_t), cmp_region_list);
371
372 11 return DLB_SUCCESS;
373 }
374
375 8 int shmem_talp__get_times(int region_id, int64_t *mpi_time, int64_t *useful_time) {
376
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (unlikely(shm_handler == NULL)) return DLB_ERR_NOSHMEM;
377
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (unlikely(region_id >= shdata->max_regions)) return DLB_ERR_NOMEM;
378
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (unlikely(region_id < 0)) return DLB_ERR_NOENT;
379
380 5 talp_region_t *talp_region = &shdata->talp_region[region_id];
381
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (unlikely(talp_region->pid == NOBODY)) return DLB_ERR_NOENT;
382
383 4 *mpi_time = DLB_ATOMIC_LD_RLX(&talp_region->mpi_time);
384 4 *useful_time = DLB_ATOMIC_LD_RLX(&talp_region->useful_time);
385
386 4 return DLB_SUCCESS;
387 }
388
389
390 /*********************************************************************************/
391 /* Setters */
392 /*********************************************************************************/
393
394 26 int shmem_talp__set_times(int region_id, int64_t mpi_time, int64_t useful_time) {
395
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 21 times.
26 if (unlikely(shm_handler == NULL)) return DLB_ERR_NOSHMEM;
396
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (unlikely(region_id >= shdata->max_regions)) return DLB_ERR_NOMEM;
397
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
20 if (unlikely(region_id < 0)) return DLB_ERR_NOENT;
398
399 19 talp_region_t *talp_region = &shdata->talp_region[region_id];
400
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (unlikely(talp_region->pid == NOBODY)) return DLB_ERR_NOENT;
401
402 18 DLB_ATOMIC_ST_RLX(&talp_region->mpi_time, mpi_time);
403 18 DLB_ATOMIC_ST_RLX(&talp_region->useful_time, useful_time);
404
405 18 return DLB_SUCCESS;
406 }
407
408 1 int shmem_talp__set_avg_cpus(int region_id, float avg_cpus) {
409
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (unlikely(shm_handler == NULL)) return DLB_ERR_NOSHMEM;
410 if (unlikely(region_id >= shdata->max_regions)) return DLB_ERR_NOMEM;
411 if (unlikely(region_id < 0)) return DLB_ERR_NOENT;
412
413 talp_region_t *talp_region = &shdata->talp_region[region_id];
414 if (unlikely(talp_region->pid == NOBODY)) return DLB_ERR_NOENT;
415
416 talp_region->avg_cpus = avg_cpus;
417
418 return DLB_SUCCESS;
419 }
420
421
422 /*********************************************************************************/
423 /* Misc */
424 /*********************************************************************************/
425
426 7 void shmem_talp__print_info(const char *shmem_key, int regions_per_process) {
427
428 /* If the shmem is not opened, obtain a temporary fd */
429 7 bool temporary_shmem = shm_handler == NULL;
430
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (temporary_shmem) {
431 6 shmem_talp_ext__init(shmem_key, regions_per_process);
432 }
433
434 /* Make a full copy of the shared memory */
435 7 shdata_t *shdata_copy = malloc(shmem_talp__size());
436 7 shmem_lock(shm_handler);
437 {
438 7 memcpy(shdata_copy, shdata, shmem_talp__size());
439 }
440 7 shmem_unlock(shm_handler);
441
442 /* Close shmem if needed */
443
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (temporary_shmem) {
444 6 shmem_talp_ext__finalize();
445 }
446
447 /* Find the max number of characters per column */
448 7 pid_t max_pid = 111; /* 3 digits for 'PID' */
449 7 int max_name = 4; /* 'Name' */
450 7 int max_mpi = 8; /* 'MPI time' */
451 7 int max_useful = 11; /* 'Useful time' */
452 int region_id;
453 7 int max_regions = shdata_copy->max_regions;
454
2/2
✓ Branch 0 taken 6400 times.
✓ Branch 1 taken 7 times.
6407 for (region_id = 0; region_id < max_regions; ++region_id) {
455 6400 talp_region_t *talp_region = &shdata_copy->talp_region[region_id];
456
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6397 times.
6400 if (talp_region->pid != NOBODY) {
457 int len;
458 /* PID */
459 3 max_pid = max_int(talp_region->pid, max_pid);
460 /* Name */
461 3 len = strlen(talp_region->name);
462 3 max_name = max_int(len, max_name);
463 /* MPI time */
464 3 len = snprintf(NULL, 0, "%"PRId64, talp_region->mpi_time);
465 3 max_mpi = max_int(len, max_mpi);
466 /* Useful time */
467 3 len = snprintf(NULL, 0, "%"PRId64, talp_region->useful_time);
468 3 max_useful = max_int(len, max_useful);
469 }
470 }
471 7 int max_pid_digits = snprintf(NULL, 0, "%d", max_pid);
472
473 /* Initialize buffer */
474 print_buffer_t buffer;
475 7 printbuffer_init(&buffer);
476
477 /* Set up line buffer */
478 enum { MAX_LINE_LEN = 512 };
479 char line[MAX_LINE_LEN];
480
481
2/2
✓ Branch 0 taken 6400 times.
✓ Branch 1 taken 7 times.
6407 for (region_id = 0; region_id < max_regions; ++region_id) {
482 6400 talp_region_t *talp_region = &shdata_copy->talp_region[region_id];
483
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6397 times.
6400 if (talp_region->pid != NOBODY) {
484
485 /* Append line to buffer */
486 3 snprintf(line, MAX_LINE_LEN,
487 " | %*d | %*s | %*"PRId64" | %*"PRId64" |",
488 max_pid_digits, talp_region->pid,
489 3 max_name, talp_region->name,
490 3 max_mpi, talp_region->mpi_time,
491 3 max_useful, talp_region->useful_time),
492 3 printbuffer_append(&buffer, line);
493 }
494 }
495
496 /* Print if not empty */
497
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (buffer.addr[0] != '\0' ) {
498 /* Construct header */
499 1 snprintf(line, MAX_LINE_LEN,
500 " | %*s | %*s | %*s | %*s |",
501 max_pid_digits, "PID",
502 max_name, "Name",
503 max_mpi, "MPI time",
504 max_useful, "Useful time");
505
506 /* Print header + buffer */
507 1 info0("=== TALP Regions ===\n"
508 "%s\n"
509 "%s", line, buffer.addr);
510 }
511
512 7 printbuffer_destroy(&buffer);
513 7 free(shdata_copy);
514 7 }
515
516 1 bool shmem_talp__exists(void) {
517 1 return shm_handler != NULL;
518 }
519
520 6 bool shmem_talp__initialized(void) {
521
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 return shdata && shdata->initialized;
522 }
523
524 1 int shmem_talp__version(void) {
525 1 return SHMEM_TALP_VERSION;
526 }
527
528 37 size_t shmem_talp__size(void) {
529 74 int regions_per_process = regions_per_proc_initialized ?
530
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1 times.
37 regions_per_proc_initialized : DEFAULT_REGIONS_PER_PROC;
531 37 int num_regions = mu_get_system_size() * regions_per_process;
532 37 return sizeof(shdata_t) + sizeof(talp_region_t)*num_regions;
533 }
534
535 3 int shmem_talp__get_max_regions(void) {
536
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 return shdata ? shdata->max_regions : 0;
537 }
538