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 |