1 /* Copyright (C) 2018-2024 Free Software Foundation, Inc.
2 Contributed by Jakub Jelinek <jakub@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
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)
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
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.
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/>. */
33 #ifdef HAVE_INTTYPES_H
34 # include <inttypes.h> /* For PRIx64. */
37 #include <sys/utsname.h>
40 ialias_redirect (omp_get_team_num
)
41 ialias_redirect (omp_get_num_teams
)
44 gomp_print_string (const char *str
, size_t len
)
46 return fwrite (str
, 1, len
, stderr
) != len
;
50 gomp_set_affinity_format (const char *format
, size_t len
)
52 if (len
< gomp_affinity_format_len
)
53 memcpy (gomp_affinity_format_var
, format
, len
);
57 if (gomp_affinity_format_len
)
58 p
= gomp_realloc (gomp_affinity_format_var
, len
+ 1);
60 p
= gomp_malloc (len
+ 1);
61 memcpy (p
, format
, len
);
62 gomp_affinity_format_var
= p
;
63 gomp_affinity_format_len
= len
+ 1;
65 gomp_affinity_format_var
[len
] = '\0';
69 omp_set_affinity_format (const char *format
)
71 gomp_set_affinity_format (format
, strlen (format
));
75 omp_get_affinity_format (char *buffer
, size_t size
)
77 size_t len
= strlen (gomp_affinity_format_var
);
81 memcpy (buffer
, gomp_affinity_format_var
, len
+ 1);
84 memcpy (buffer
, gomp_affinity_format_var
, size
- 1);
85 buffer
[size
- 1] = '\0';
92 gomp_display_string (char *buffer
, size_t size
, size_t *ret
,
93 const char *str
, size_t len
)
101 memcpy (buffer
+ r
, str
, l
);
104 if (__builtin_expect (r
> *ret
, 0))
105 gomp_fatal ("overflow in omp_capture_affinity");
109 gomp_display_repeat (char *buffer
, size_t size
, size_t *ret
,
113 if (size
&& r
< size
)
118 memset (buffer
+ r
, c
, l
);
121 if (__builtin_expect (r
> *ret
, 0))
122 gomp_fatal ("overflow in omp_capture_affinity");
126 gomp_display_num (char *buffer
, size_t size
, size_t *ret
,
127 bool zero
, bool right
, size_t sz
, char *buf
)
129 size_t l
= strlen (buf
);
130 if (sz
== (size_t) -1 || l
>= sz
)
132 gomp_display_string (buffer
, size
, ret
, buf
, l
);
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
);
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);
147 gomp_display_string (buffer
, size
, ret
, buf
, l
);
151 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- l
);
152 gomp_display_string (buffer
, size
, ret
, buf
, l
);
156 gomp_display_string (buffer
, size
, ret
, buf
, l
);
157 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- l
);
162 gomp_display_int (char *buffer
, size_t size
, size_t *ret
,
163 bool zero
, bool right
, size_t sz
, int num
)
165 char buf
[3 * sizeof (int) + 2];
166 sprintf (buf
, "%d", num
);
167 gomp_display_num (buffer
, size
, ret
, zero
, right
, sz
, buf
);
171 gomp_display_string_len (char *buffer
, size_t size
, size_t *ret
,
172 bool right
, size_t sz
, char *str
, size_t len
)
174 if (sz
== (size_t) -1 || len
>= sz
)
176 gomp_display_string (buffer
, size
, ret
, str
, len
);
182 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- len
);
183 gomp_display_string (buffer
, size
, ret
, str
, len
);
187 gomp_display_string (buffer
, size
, ret
, str
, len
);
188 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- len
);
193 gomp_display_hostname (char *buffer
, size_t size
, size_t *ret
,
194 bool right
, size_t sz
)
196 #ifdef HAVE_GETHOSTNAME
204 if (gethostname (b
, len
- 1) == 0)
206 size_t l
= strlen (b
);
209 gomp_display_string_len (buffer
, size
, ret
,
220 b
= gomp_malloc (len
);
222 b
= gomp_realloc (b
, len
);
232 if (uname (&buf
) == 0)
234 gomp_display_string_len (buffer
, size
, ret
, right
, sz
,
235 buf
.nodename
, strlen (buf
.nodename
));
240 gomp_display_string_len (buffer
, size
, ret
, right
, sz
, "node", 4);
243 struct affinity_types_struct
{
248 static struct affinity_types_struct affinity_types
[] =
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')
266 gomp_display_affinity (char *buffer
, size_t size
,
267 const char *format
, gomp_thread_handle handle
,
268 struct gomp_team_state
*ts
, unsigned int place
)
273 const char *p
= strchr (format
, '%');
280 p
= strchr (format
, '\0');
282 gomp_display_string (buffer
, size
, &ret
,
289 gomp_display_string (buffer
, size
, &ret
, "%", 1);
298 gomp_fatal ("leading zero not followed by dot in affinity format");
305 if (*p
>= '1' && *p
<= '9')
308 sz
= strtoul (p
, &end
, 10);
311 else if (zero
|| right
)
312 gomp_fatal ("leading zero or right justification in affinity format "
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] == '}')
324 c
= affinity_types
[i
].short_c
;
325 p
+= affinity_types
[i
].long_len
+ 1;
330 char *q
= strchr (p
+ 1, '}');
332 gomp_fatal ("unsupported long type name '%.*s' in affinity "
333 "format", (int) (q
- (p
+ 1)), p
+ 1);
335 gomp_fatal ("unterminated long type name '%s' in affinity "
342 val
= omp_get_team_num ();
345 val
= omp_get_num_teams ();
354 val
= ts
->team
? ts
->team
->nthreads
: 1;
357 val
= ts
->team
? ts
->team
->prev_ts
.team_id
: -1;
360 gomp_display_hostname (buffer
, size
, &ret
, right
, sz
);
370 #if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__)
372 char buf
[3 * (sizeof (handle
) + sizeof (uintptr_t) + sizeof (int))
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))
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
));
393 else if (sizeof (gomp_integral (handle
))
394 == sizeof (unsigned long long))
395 sprintf (buf
, "0x%llx",
396 (unsigned long long) gomp_integral (handle
));
399 sprintf (buf
, "0x%x", (unsigned int) gomp_integral (handle
));
400 gomp_display_num (buffer
, size
, &ret
, zero
, right
, sz
, buf
);
408 if (sz
== (size_t) -1)
409 gomp_display_affinity_place (buffer
, size
, &ret
,
414 gomp_display_affinity_place (NULL
, 0, &len
, place
- 1);
416 gomp_display_repeat (buffer
, size
, &ret
, ' ', sz
- len
);
417 gomp_display_affinity_place (buffer
, size
, &ret
, place
- 1);
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
));
428 gomp_display_int (buffer
, size
, &ret
, zero
, right
, sz
, val
);
431 gomp_fatal ("unsupported type %c in affinity format", c
);
440 omp_capture_affinity (char *buffer
, size_t size
, const char *format
)
442 struct gomp_thread
*thr
= gomp_thread ();
444 = gomp_display_affinity (buffer
, size
,
446 ? format
: gomp_affinity_format_var
,
447 gomp_thread_self (), &thr
->ts
, thr
->place
);
451 buffer
[size
- 1] = '\0';
457 ialias (omp_capture_affinity
)
460 omp_display_affinity (const char *format
)
464 size_t ret
= ialias_call (omp_capture_affinity
) (buf
, sizeof buf
, format
);
465 if (ret
< sizeof buf
)
468 gomp_print_string (buf
, ret
+ 1);
471 b
= gomp_malloc (ret
+ 1);
472 ialias_call (omp_capture_affinity
) (b
, ret
+ 1, format
);
474 gomp_print_string (b
, ret
+ 1);
479 gomp_display_affinity_thread (gomp_thread_handle handle
,
480 struct gomp_team_state
*ts
, unsigned int place
)
484 size_t ret
= gomp_display_affinity (buf
, sizeof buf
, gomp_affinity_format_var
,
486 if (ret
< sizeof buf
)
489 gomp_print_string (buf
, ret
+ 1);
492 b
= gomp_malloc (ret
+ 1);
493 gomp_display_affinity (b
, ret
+ 1, gomp_affinity_format_var
,
496 gomp_print_string (b
, ret
+ 1);