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