1 /* Copyright (C) 2018-2019 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>
41 gomp_print_string (const char *str
, size_t len
)
43 fwrite (str
, 1, len
, stderr
);
47 gomp_set_affinity_format (const char *format
, size_t len
)
49 if (len
< gomp_affinity_format_len
)
50 memcpy (gomp_affinity_format_var
, format
, len
);
54 if (gomp_affinity_format_len
)
55 p
= gomp_realloc (gomp_affinity_format_var
, len
+ 1);
57 p
= gomp_malloc (len
+ 1);
58 memcpy (p
, format
, len
);
59 gomp_affinity_format_var
= p
;
60 gomp_affinity_format_len
= len
+ 1;
62 gomp_affinity_format_var
[len
] = '\0';
66 omp_set_affinity_format (const char *format
)
68 gomp_set_affinity_format (format
, strlen (format
));
72 omp_get_affinity_format (char *buffer
, size_t size
)
74 size_t len
= strlen (gomp_affinity_format_var
);
78 memcpy (buffer
, gomp_affinity_format_var
, len
+ 1);
81 memcpy (buffer
, gomp_affinity_format_var
, size
- 1);
82 buffer
[size
- 1] = '\0';
89 gomp_display_string (char *buffer
, size_t size
, size_t *ret
,
90 const char *str
, size_t len
)
98 memcpy (buffer
+ r
, str
, l
);
101 if (__builtin_expect (r
> *ret
, 0))
102 gomp_fatal ("overflow in omp_capture_affinity");
106 gomp_display_repeat (char *buffer
, size_t size
, size_t *ret
,
110 if (size
&& r
< size
)
115 memset (buffer
+ r
, c
, l
);
118 if (__builtin_expect (r
> *ret
, 0))
119 gomp_fatal ("overflow in omp_capture_affinity");
123 gomp_display_num (char *buffer
, size_t size
, size_t *ret
,
124 bool zero
, bool right
, size_t sz
, char *buf
)
126 size_t l
= strlen (buf
);
127 if (sz
== (size_t) -1 || l
>= sz
)
129 gomp_display_string (buffer
, size
, ret
, buf
, l
);
135 gomp_display_string (buffer
, size
, ret
, buf
, 1);
136 else if (buf
[0] == '0' && buf
[1] == 'x')
137 gomp_display_string (buffer
, size
, ret
, buf
, 2);
138 gomp_display_repeat (buffer
, size
, ret
, '0', sz
- l
);
140 gomp_display_string (buffer
, size
, ret
, buf
+ 1, l
- 1);
141 else if (buf
[0] == '0' && buf
[1] == 'x')
142 gomp_display_string (buffer
, size
, ret
, buf
+ 2, l
- 2);
144 gomp_display_string (buffer
, size
, ret
, buf
, l
);
148 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- l
);
149 gomp_display_string (buffer
, size
, ret
, buf
, l
);
153 gomp_display_string (buffer
, size
, ret
, buf
, l
);
154 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- l
);
159 gomp_display_int (char *buffer
, size_t size
, size_t *ret
,
160 bool zero
, bool right
, size_t sz
, int num
)
162 char buf
[3 * sizeof (int) + 2];
163 sprintf (buf
, "%d", num
);
164 gomp_display_num (buffer
, size
, ret
, zero
, right
, sz
, buf
);
168 gomp_display_string_len (char *buffer
, size_t size
, size_t *ret
,
169 bool right
, size_t sz
, char *str
, size_t len
)
171 if (sz
== (size_t) -1 || len
>= sz
)
173 gomp_display_string (buffer
, size
, ret
, str
, len
);
179 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- len
);
180 gomp_display_string (buffer
, size
, ret
, str
, len
);
184 gomp_display_string (buffer
, size
, ret
, str
, len
);
185 gomp_display_repeat (buffer
, size
, ret
, ' ', sz
- len
);
190 gomp_display_hostname (char *buffer
, size_t size
, size_t *ret
,
191 bool right
, size_t sz
)
193 #ifdef HAVE_GETHOSTNAME
201 if (gethostname (b
, len
- 1) == 0)
203 size_t l
= strlen (b
);
206 gomp_display_string_len (buffer
, size
, ret
,
217 b
= gomp_malloc (len
);
219 b
= gomp_realloc (b
, len
);
229 if (uname (&buf
) == 0)
231 gomp_display_string_len (buffer
, size
, ret
, right
, sz
,
232 buf
.nodename
, strlen (buf
.nodename
));
237 gomp_display_string_len (buffer
, size
, ret
, right
, sz
, "node", 4);
240 struct affinity_types_struct
{
245 static struct affinity_types_struct affinity_types
[] =
247 #define AFFINITY_TYPE(l, s) \
248 { #l, sizeof (#l) - 1, s }
249 AFFINITY_TYPE (team_num
, 't'),
250 AFFINITY_TYPE (num_teams
, 'T'),
251 AFFINITY_TYPE (nesting_level
, 'L'),
252 AFFINITY_TYPE (thread_num
, 'n'),
253 AFFINITY_TYPE (num_threads
, 'N'),
254 AFFINITY_TYPE (ancestor_tnum
, 'a'),
255 AFFINITY_TYPE (host
, 'H'),
256 AFFINITY_TYPE (process_id
, 'P'),
257 AFFINITY_TYPE (native_thread_id
, 'i'),
258 AFFINITY_TYPE (thread_affinity
, 'A')
263 gomp_display_affinity (char *buffer
, size_t size
,
264 const char *format
, gomp_thread_handle handle
,
265 struct gomp_team_state
*ts
, unsigned int place
)
270 const char *p
= strchr (format
, '%');
277 p
= strchr (format
, '\0');
279 gomp_display_string (buffer
, size
, &ret
,
286 gomp_display_string (buffer
, size
, &ret
, "%", 1);
295 gomp_fatal ("leading zero not followed by dot in affinity format");
302 if (*p
>= '1' && *p
<= '9')
305 sz
= strtoul (p
, &end
, 10);
308 else if (zero
|| right
)
309 gomp_fatal ("leading zero or right justification in affinity format "
316 i
< sizeof (affinity_types
) / sizeof (affinity_types
[0]); ++i
)
317 if (strncmp (p
+ 1, affinity_types
[i
].long_str
,
318 affinity_types
[i
].long_len
) == 0
319 && p
[affinity_types
[i
].long_len
+ 1] == '}')
321 c
= affinity_types
[i
].short_c
;
322 p
+= affinity_types
[i
].long_len
+ 1;
327 char *q
= strchr (p
+ 1, '}');
329 gomp_fatal ("unsupported long type name '%.*s' in affinity "
330 "format", (int) (q
- (p
+ 1)), p
+ 1);
332 gomp_fatal ("unterminated long type name '%s' in affinity "
339 val
= omp_get_team_num ();
342 val
= omp_get_num_teams ();
351 val
= ts
->team
? ts
->team
->nthreads
: 1;
354 val
= ts
->team
? ts
->team
->prev_ts
.team_id
: -1;
357 gomp_display_hostname (buffer
, size
, &ret
, right
, sz
);
367 #if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__)
369 char buf
[3 * (sizeof (handle
) + sizeof (uintptr_t) + sizeof (int))
371 /* This macro returns expr unmodified for integral or pointer
372 types and 0 for anything else (e.g. aggregates). */
373 #define gomp_nonaggregate(expr) \
374 __builtin_choose_expr (__builtin_classify_type (expr) == 1 \
375 || __builtin_classify_type (expr) == 5, expr, 0)
376 /* This macro returns expr unmodified for integral types,
377 (uintptr_t) (expr) for pointer types and 0 for anything else
378 (e.g. aggregates). */
379 #define gomp_integral(expr) \
380 __builtin_choose_expr (__builtin_classify_type (expr) == 5, \
381 (uintptr_t) gomp_nonaggregate (expr), \
382 gomp_nonaggregate (expr))
384 if (sizeof (gomp_integral (handle
)) == sizeof (unsigned long))
385 sprintf (buf
, "0x%lx", (unsigned long) gomp_integral (handle
));
386 #if defined (HAVE_INTTYPES_H) && defined (PRIx64)
387 else if (sizeof (gomp_integral (handle
)) == sizeof (uint64_t))
388 sprintf (buf
, "0x%" PRIx64
, (uint64_t) gomp_integral (handle
));
390 else if (sizeof (gomp_integral (handle
))
391 == sizeof (unsigned long long))
392 sprintf (buf
, "0x%llx",
393 (unsigned long long) gomp_integral (handle
));
396 sprintf (buf
, "0x%x", (unsigned int) gomp_integral (handle
));
397 gomp_display_num (buffer
, size
, &ret
, zero
, right
, sz
, buf
);
405 if (sz
== (size_t) -1)
406 gomp_display_affinity_place (buffer
, size
, &ret
,
411 gomp_display_affinity_place (NULL
, 0, &len
, place
- 1);
413 gomp_display_repeat (buffer
, size
, &ret
, ' ', sz
- len
);
414 gomp_display_affinity_place (buffer
, size
, &ret
, place
- 1);
419 gomp_display_affinity_place (buffer
, size
, &ret
, place
- 1);
420 if (ret
- start
< sz
)
421 gomp_display_repeat (buffer
, size
, &ret
, ' ', sz
- (ret
- start
));
425 gomp_display_int (buffer
, size
, &ret
, zero
, right
, sz
, val
);
428 gomp_fatal ("unsupported type %c in affinity format", c
);
437 omp_capture_affinity (char *buffer
, size_t size
, const char *format
)
439 struct gomp_thread
*thr
= gomp_thread ();
441 = gomp_display_affinity (buffer
, size
,
443 ? format
: gomp_affinity_format_var
,
444 gomp_thread_self (), &thr
->ts
, thr
->place
);
448 buffer
[size
- 1] = '\0';
454 ialias (omp_capture_affinity
)
457 omp_display_affinity (const char *format
)
461 size_t ret
= ialias_call (omp_capture_affinity
) (buf
, sizeof buf
, format
);
462 if (ret
< sizeof buf
)
465 gomp_print_string (buf
, ret
+ 1);
468 b
= gomp_malloc (ret
+ 1);
469 ialias_call (omp_capture_affinity
) (b
, ret
+ 1, format
);
471 gomp_print_string (b
, ret
+ 1);
476 gomp_display_affinity_thread (gomp_thread_handle handle
,
477 struct gomp_team_state
*ts
, unsigned int place
)
481 size_t ret
= gomp_display_affinity (buf
, sizeof buf
, gomp_affinity_format_var
,
483 if (ret
< sizeof buf
)
486 gomp_print_string (buf
, ret
+ 1);
489 b
= gomp_malloc (ret
+ 1);
490 gomp_display_affinity (b
, ret
+ 1, gomp_affinity_format_var
,
493 gomp_print_string (b
, ret
+ 1);