]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgomp/affinity-fmt.c
Fix tests for gomp
[thirdparty/gcc.git] / libgomp / affinity-fmt.c
CommitLineData
83ffe9cd 1/* Copyright (C) 2018-2023 Free Software Foundation, Inc.
28567c40
JJ
2 Contributed by Jakub Jelinek <jakub@redhat.com>.
3
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
6
7 Libgomp is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
25
26#include "libgomp.h"
27#include <string.h>
28#include <stdio.h>
29#include <stdlib.h>
30#ifdef HAVE_UNISTD_H
31#include <unistd.h>
32#endif
9666c522
JJ
33#ifdef HAVE_INTTYPES_H
34# include <inttypes.h> /* For PRIx64. */
35#endif
28567c40
JJ
36#ifdef HAVE_UNAME
37#include <sys/utsname.h>
38#endif
39
3749c3af
JJ
40ialias_redirect (omp_get_team_num)
41ialias_redirect (omp_get_num_teams)
42
91df4397 43bool
fe0827ee
TV
44gomp_print_string (const char *str, size_t len)
45{
91df4397 46 return fwrite (str, 1, len, stderr) != len;
fe0827ee
TV
47}
48
28567c40
JJ
49void
50gomp_set_affinity_format (const char *format, size_t len)
51{
52 if (len < gomp_affinity_format_len)
53 memcpy (gomp_affinity_format_var, format, len);
54 else
55 {
56 char *p;
57 if (gomp_affinity_format_len)
58 p = gomp_realloc (gomp_affinity_format_var, len + 1);
59 else
60 p = gomp_malloc (len + 1);
61 memcpy (p, format, len);
62 gomp_affinity_format_var = p;
63 gomp_affinity_format_len = len + 1;
64 }
65 gomp_affinity_format_var[len] = '\0';
66}
67
68void
69omp_set_affinity_format (const char *format)
70{
71 gomp_set_affinity_format (format, strlen (format));
72}
73
74size_t
75omp_get_affinity_format (char *buffer, size_t size)
76{
77 size_t len = strlen (gomp_affinity_format_var);
78 if (size)
79 {
80 if (len < size)
81 memcpy (buffer, gomp_affinity_format_var, len + 1);
82 else
83 {
84 memcpy (buffer, gomp_affinity_format_var, size - 1);
85 buffer[size - 1] = '\0';
86 }
87 }
88 return len;
89}
90
91void
92gomp_display_string (char *buffer, size_t size, size_t *ret,
93 const char *str, size_t len)
94{
95 size_t r = *ret;
96 if (size && r < size)
97 {
98 size_t l = len;
99 if (size - r < len)
100 l = size - r;
101 memcpy (buffer + r, str, l);
102 }
103 *ret += len;
104 if (__builtin_expect (r > *ret, 0))
105 gomp_fatal ("overflow in omp_capture_affinity");
106}
107
108static void
109gomp_display_repeat (char *buffer, size_t size, size_t *ret,
110 char c, size_t len)
111{
112 size_t r = *ret;
113 if (size && r < size)
114 {
115 size_t l = len;
116 if (size - r < len)
117 l = size - r;
118 memset (buffer + r, c, l);
119 }
120 *ret += len;
121 if (__builtin_expect (r > *ret, 0))
122 gomp_fatal ("overflow in omp_capture_affinity");
123}
124
125static void
126gomp_display_num (char *buffer, size_t size, size_t *ret,
127 bool zero, bool right, size_t sz, char *buf)
128{
129 size_t l = strlen (buf);
130 if (sz == (size_t) -1 || l >= sz)
131 {
132 gomp_display_string (buffer, size, ret, buf, l);
133 return;
134 }
135 if (zero)
136 {
137 if (buf[0] == '-')
138 gomp_display_string (buffer, size, ret, buf, 1);
139 else if (buf[0] == '0' && buf[1] == 'x')
140 gomp_display_string (buffer, size, ret, buf, 2);
141 gomp_display_repeat (buffer, size, ret, '0', sz - l);
142 if (buf[0] == '-')
143 gomp_display_string (buffer, size, ret, buf + 1, l - 1);
144 else if (buf[0] == '0' && buf[1] == 'x')
145 gomp_display_string (buffer, size, ret, buf + 2, l - 2);
146 else
147 gomp_display_string (buffer, size, ret, buf, l);
148 }
149 else if (right)
150 {
151 gomp_display_repeat (buffer, size, ret, ' ', sz - l);
152 gomp_display_string (buffer, size, ret, buf, l);
153 }
154 else
155 {
156 gomp_display_string (buffer, size, ret, buf, l);
157 gomp_display_repeat (buffer, size, ret, ' ', sz - l);
158 }
159}
160
161static void
162gomp_display_int (char *buffer, size_t size, size_t *ret,
163 bool zero, bool right, size_t sz, int num)
164{
165 char buf[3 * sizeof (int) + 2];
166 sprintf (buf, "%d", num);
167 gomp_display_num (buffer, size, ret, zero, right, sz, buf);
168}
169
170static void
171gomp_display_string_len (char *buffer, size_t size, size_t *ret,
172 bool right, size_t sz, char *str, size_t len)
173{
174 if (sz == (size_t) -1 || len >= sz)
175 {
176 gomp_display_string (buffer, size, ret, str, len);
177 return;
178 }
179
180 if (right)
181 {
182 gomp_display_repeat (buffer, size, ret, ' ', sz - len);
183 gomp_display_string (buffer, size, ret, str, len);
184 }
185 else
186 {
187 gomp_display_string (buffer, size, ret, str, len);
188 gomp_display_repeat (buffer, size, ret, ' ', sz - len);
189 }
190}
191
192static void
193gomp_display_hostname (char *buffer, size_t size, size_t *ret,
194 bool right, size_t sz)
195{
196#ifdef HAVE_GETHOSTNAME
197 {
198 char buf[256];
199 char *b = buf;
200 size_t len = 256;
201 do
202 {
203 b[len - 1] = '\0';
204 if (gethostname (b, len - 1) == 0)
205 {
206 size_t l = strlen (b);
207 if (l < len - 1)
208 {
209 gomp_display_string_len (buffer, size, ret,
210 right, sz, b, l);
211 if (b != buf)
212 free (b);
213 return;
214 }
215 }
216 if (len == 1048576)
217 break;
218 len = len * 2;
219 if (len == 512)
220 b = gomp_malloc (len);
221 else
222 b = gomp_realloc (b, len);
223 }
224 while (1);
225 if (b != buf)
226 free (b);
227 }
228#endif
229#ifdef HAVE_UNAME
230 {
231 struct utsname buf;
232 if (uname (&buf) == 0)
233 {
234 gomp_display_string_len (buffer, size, ret, right, sz,
235 buf.nodename, strlen (buf.nodename));
236 return;
237 }
238 }
239#endif
240 gomp_display_string_len (buffer, size, ret, right, sz, "node", 4);
241}
242
243struct affinity_types_struct {
244 char long_str[18];
245 char long_len;
246 char short_c; };
247
248static struct affinity_types_struct affinity_types[] =
249{
250#define AFFINITY_TYPE(l, s) \
251 { #l, sizeof (#l) - 1, s }
252 AFFINITY_TYPE (team_num, 't'),
253 AFFINITY_TYPE (num_teams, 'T'),
254 AFFINITY_TYPE (nesting_level, 'L'),
255 AFFINITY_TYPE (thread_num, 'n'),
256 AFFINITY_TYPE (num_threads, 'N'),
257 AFFINITY_TYPE (ancestor_tnum, 'a'),
258 AFFINITY_TYPE (host, 'H'),
259 AFFINITY_TYPE (process_id, 'P'),
260 AFFINITY_TYPE (native_thread_id, 'i'),
261 AFFINITY_TYPE (thread_affinity, 'A')
262#undef AFFINITY_TYPE
263};
264
265size_t
266gomp_display_affinity (char *buffer, size_t size,
267 const char *format, gomp_thread_handle handle,
268 struct gomp_team_state *ts, unsigned int place)
269{
270 size_t ret = 0;
271 do
272 {
273 const char *p = strchr (format, '%');
274 bool zero = false;
275 bool right = false;
276 size_t sz = -1;
277 char c;
278 int val;
279 if (p == NULL)
280 p = strchr (format, '\0');
281 if (p != format)
282 gomp_display_string (buffer, size, &ret,
283 format, p - format);
284 if (*p == '\0')
285 break;
286 p++;
287 if (*p == '%')
288 {
289 gomp_display_string (buffer, size, &ret, "%", 1);
290 format = p + 1;
291 continue;
292 }
293 if (*p == '0')
294 {
295 zero = true;
296 p++;
297 if (*p != '.')
298 gomp_fatal ("leading zero not followed by dot in affinity format");
299 }
300 if (*p == '.')
301 {
302 right = true;
303 p++;
304 }
305 if (*p >= '1' && *p <= '9')
306 {
307 char *end;
308 sz = strtoul (p, &end, 10);
309 p = end;
310 }
311 else if (zero || right)
312 gomp_fatal ("leading zero or right justification in affinity format "
313 "requires size");
314 c = *p;
315 if (c == '{')
316 {
317 int i;
318 for (i = 0;
319 i < sizeof (affinity_types) / sizeof (affinity_types[0]); ++i)
320 if (strncmp (p + 1, affinity_types[i].long_str,
321 affinity_types[i].long_len) == 0
322 && p[affinity_types[i].long_len + 1] == '}')
323 {
324 c = affinity_types[i].short_c;
325 p += affinity_types[i].long_len + 1;
326 break;
327 }
328 if (c == '{')
329 {
330 char *q = strchr (p + 1, '}');
331 if (q)
332 gomp_fatal ("unsupported long type name '%.*s' in affinity "
333 "format", (int) (q - (p + 1)), p + 1);
334 else
335 gomp_fatal ("unterminated long type name '%s' in affinity "
336 "format", p + 1);
337 }
338 }
339 switch (c)
340 {
341 case 't':
342 val = omp_get_team_num ();
343 goto do_int;
344 case 'T':
345 val = omp_get_num_teams ();
346 goto do_int;
347 case 'L':
348 val = ts->level;
349 goto do_int;
350 case 'n':
351 val = ts->team_id;
352 goto do_int;
353 case 'N':
354 val = ts->team ? ts->team->nthreads : 1;
355 goto do_int;
356 case 'a':
357 val = ts->team ? ts->team->prev_ts.team_id : -1;
358 goto do_int;
359 case 'H':
360 gomp_display_hostname (buffer, size, &ret, right, sz);
361 break;
362 case 'P':
363#ifdef HAVE_GETPID
364 val = getpid ();
365#else
366 val = 0;
367#endif
368 goto do_int;
369 case 'i':
370#if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__)
9666c522
JJ
371 {
372 char buf[3 * (sizeof (handle) + sizeof (uintptr_t) + sizeof (int))
373 + 4];
374 /* This macro returns expr unmodified for integral or pointer
375 types and 0 for anything else (e.g. aggregates). */
376#define gomp_nonaggregate(expr) \
377 __builtin_choose_expr (__builtin_classify_type (expr) == 1 \
378 || __builtin_classify_type (expr) == 5, expr, 0)
379 /* This macro returns expr unmodified for integral types,
380 (uintptr_t) (expr) for pointer types and 0 for anything else
381 (e.g. aggregates). */
382#define gomp_integral(expr) \
383 __builtin_choose_expr (__builtin_classify_type (expr) == 5, \
384 (uintptr_t) gomp_nonaggregate (expr), \
385 gomp_nonaggregate (expr))
28567c40 386
9666c522
JJ
387 if (sizeof (gomp_integral (handle)) == sizeof (unsigned long))
388 sprintf (buf, "0x%lx", (unsigned long) gomp_integral (handle));
389#if defined (HAVE_INTTYPES_H) && defined (PRIx64)
390 else if (sizeof (gomp_integral (handle)) == sizeof (uint64_t))
391 sprintf (buf, "0x%" PRIx64, (uint64_t) gomp_integral (handle));
392#else
393 else if (sizeof (gomp_integral (handle))
394 == sizeof (unsigned long long))
395 sprintf (buf, "0x%llx",
396 (unsigned long long) gomp_integral (handle));
28567c40 397#endif
9666c522
JJ
398 else
399 sprintf (buf, "0x%x", (unsigned int) gomp_integral (handle));
400 gomp_display_num (buffer, size, &ret, zero, right, sz, buf);
401 break;
402 }
403#else
28567c40
JJ
404 val = 0;
405 goto do_int;
9666c522 406#endif
28567c40
JJ
407 case 'A':
408 if (sz == (size_t) -1)
409 gomp_display_affinity_place (buffer, size, &ret,
410 place - 1);
411 else if (right)
412 {
413 size_t len = 0;
414 gomp_display_affinity_place (NULL, 0, &len, place - 1);
415 if (len < sz)
416 gomp_display_repeat (buffer, size, &ret, ' ', sz - len);
417 gomp_display_affinity_place (buffer, size, &ret, place - 1);
418 }
419 else
420 {
421 size_t start = ret;
422 gomp_display_affinity_place (buffer, size, &ret, place - 1);
423 if (ret - start < sz)
424 gomp_display_repeat (buffer, size, &ret, ' ', sz - (ret - start));
425 }
426 break;
427 do_int:
428 gomp_display_int (buffer, size, &ret, zero, right, sz, val);
429 break;
430 default:
431 gomp_fatal ("unsupported type %c in affinity format", c);
432 }
433 format = p + 1;
434 }
435 while (1);
436 return ret;
437}
438
439size_t
440omp_capture_affinity (char *buffer, size_t size, const char *format)
441{
442 struct gomp_thread *thr = gomp_thread ();
443 size_t ret
444 = gomp_display_affinity (buffer, size,
445 format && *format
446 ? format : gomp_affinity_format_var,
447 gomp_thread_self (), &thr->ts, thr->place);
448 if (size)
449 {
450 if (ret >= size)
451 buffer[size - 1] = '\0';
452 else
453 buffer[ret] = '\0';
454 }
455 return ret;
456}
457ialias (omp_capture_affinity)
458
459void
460omp_display_affinity (const char *format)
461{
462 char buf[512];
463 char *b;
464 size_t ret = ialias_call (omp_capture_affinity) (buf, sizeof buf, format);
465 if (ret < sizeof buf)
466 {
467 buf[ret] = '\n';
fe0827ee 468 gomp_print_string (buf, ret + 1);
28567c40
JJ
469 return;
470 }
471 b = gomp_malloc (ret + 1);
472 ialias_call (omp_capture_affinity) (b, ret + 1, format);
473 b[ret] = '\n';
fe0827ee 474 gomp_print_string (b, ret + 1);
28567c40
JJ
475 free (b);
476}
477
478void
479gomp_display_affinity_thread (gomp_thread_handle handle,
480 struct gomp_team_state *ts, unsigned int place)
481{
482 char buf[512];
483 char *b;
484 size_t ret = gomp_display_affinity (buf, sizeof buf, gomp_affinity_format_var,
485 handle, ts, place);
486 if (ret < sizeof buf)
487 {
488 buf[ret] = '\n';
fe0827ee 489 gomp_print_string (buf, ret + 1);
28567c40
JJ
490 return;
491 }
492 b = gomp_malloc (ret + 1);
493 gomp_display_affinity (b, ret + 1, gomp_affinity_format_var,
494 handle, ts, place);
495 b[ret] = '\n';
fe0827ee 496 gomp_print_string (b, ret + 1);
28567c40
JJ
497 free (b);
498}