config.gcc (hppa*-*-linux*): Add pa/t-pa to tmake_file.
[official-gcc.git] / libgomp / affinity-fmt.c
blob9e5c5f754eb490682a832b232b9924e0337225e8
1 /* Copyright (C) 2018 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
5 (libgomp).
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.
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.
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/>. */
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
33 #ifdef HAVE_INTTYPES_H
34 # include <inttypes.h> /* For PRIx64. */
35 #endif
36 #ifdef HAVE_UNAME
37 #include <sys/utsname.h>
38 #endif
40 void
41 gomp_set_affinity_format (const char *format, size_t len)
43 if (len < gomp_affinity_format_len)
44 memcpy (gomp_affinity_format_var, format, len);
45 else
47 char *p;
48 if (gomp_affinity_format_len)
49 p = gomp_realloc (gomp_affinity_format_var, len + 1);
50 else
51 p = gomp_malloc (len + 1);
52 memcpy (p, format, len);
53 gomp_affinity_format_var = p;
54 gomp_affinity_format_len = len + 1;
56 gomp_affinity_format_var[len] = '\0';
59 void
60 omp_set_affinity_format (const char *format)
62 gomp_set_affinity_format (format, strlen (format));
65 size_t
66 omp_get_affinity_format (char *buffer, size_t size)
68 size_t len = strlen (gomp_affinity_format_var);
69 if (size)
71 if (len < size)
72 memcpy (buffer, gomp_affinity_format_var, len + 1);
73 else
75 memcpy (buffer, gomp_affinity_format_var, size - 1);
76 buffer[size - 1] = '\0';
79 return len;
82 void
83 gomp_display_string (char *buffer, size_t size, size_t *ret,
84 const char *str, size_t len)
86 size_t r = *ret;
87 if (size && r < size)
89 size_t l = len;
90 if (size - r < len)
91 l = size - r;
92 memcpy (buffer + r, str, l);
94 *ret += len;
95 if (__builtin_expect (r > *ret, 0))
96 gomp_fatal ("overflow in omp_capture_affinity");
99 static void
100 gomp_display_repeat (char *buffer, size_t size, size_t *ret,
101 char c, size_t len)
103 size_t r = *ret;
104 if (size && r < size)
106 size_t l = len;
107 if (size - r < len)
108 l = size - r;
109 memset (buffer + r, c, l);
111 *ret += len;
112 if (__builtin_expect (r > *ret, 0))
113 gomp_fatal ("overflow in omp_capture_affinity");
116 static void
117 gomp_display_num (char *buffer, size_t size, size_t *ret,
118 bool zero, bool right, size_t sz, char *buf)
120 size_t l = strlen (buf);
121 if (sz == (size_t) -1 || l >= sz)
123 gomp_display_string (buffer, size, ret, buf, l);
124 return;
126 if (zero)
128 if (buf[0] == '-')
129 gomp_display_string (buffer, size, ret, buf, 1);
130 else if (buf[0] == '0' && buf[1] == 'x')
131 gomp_display_string (buffer, size, ret, buf, 2);
132 gomp_display_repeat (buffer, size, ret, '0', sz - l);
133 if (buf[0] == '-')
134 gomp_display_string (buffer, size, ret, buf + 1, l - 1);
135 else if (buf[0] == '0' && buf[1] == 'x')
136 gomp_display_string (buffer, size, ret, buf + 2, l - 2);
137 else
138 gomp_display_string (buffer, size, ret, buf, l);
140 else if (right)
142 gomp_display_repeat (buffer, size, ret, ' ', sz - l);
143 gomp_display_string (buffer, size, ret, buf, l);
145 else
147 gomp_display_string (buffer, size, ret, buf, l);
148 gomp_display_repeat (buffer, size, ret, ' ', sz - l);
152 static void
153 gomp_display_int (char *buffer, size_t size, size_t *ret,
154 bool zero, bool right, size_t sz, int num)
156 char buf[3 * sizeof (int) + 2];
157 sprintf (buf, "%d", num);
158 gomp_display_num (buffer, size, ret, zero, right, sz, buf);
161 static void
162 gomp_display_string_len (char *buffer, size_t size, size_t *ret,
163 bool right, size_t sz, char *str, size_t len)
165 if (sz == (size_t) -1 || len >= sz)
167 gomp_display_string (buffer, size, ret, str, len);
168 return;
171 if (right)
173 gomp_display_repeat (buffer, size, ret, ' ', sz - len);
174 gomp_display_string (buffer, size, ret, str, len);
176 else
178 gomp_display_string (buffer, size, ret, str, len);
179 gomp_display_repeat (buffer, size, ret, ' ', sz - len);
183 static void
184 gomp_display_hostname (char *buffer, size_t size, size_t *ret,
185 bool right, size_t sz)
187 #ifdef HAVE_GETHOSTNAME
189 char buf[256];
190 char *b = buf;
191 size_t len = 256;
194 b[len - 1] = '\0';
195 if (gethostname (b, len - 1) == 0)
197 size_t l = strlen (b);
198 if (l < len - 1)
200 gomp_display_string_len (buffer, size, ret,
201 right, sz, b, l);
202 if (b != buf)
203 free (b);
204 return;
207 if (len == 1048576)
208 break;
209 len = len * 2;
210 if (len == 512)
211 b = gomp_malloc (len);
212 else
213 b = gomp_realloc (b, len);
215 while (1);
216 if (b != buf)
217 free (b);
219 #endif
220 #ifdef HAVE_UNAME
222 struct utsname buf;
223 if (uname (&buf) == 0)
225 gomp_display_string_len (buffer, size, ret, right, sz,
226 buf.nodename, strlen (buf.nodename));
227 return;
230 #endif
231 gomp_display_string_len (buffer, size, ret, right, sz, "node", 4);
234 struct affinity_types_struct {
235 char long_str[18];
236 char long_len;
237 char short_c; };
239 static struct affinity_types_struct affinity_types[] =
241 #define AFFINITY_TYPE(l, s) \
242 { #l, sizeof (#l) - 1, s }
243 AFFINITY_TYPE (team_num, 't'),
244 AFFINITY_TYPE (num_teams, 'T'),
245 AFFINITY_TYPE (nesting_level, 'L'),
246 AFFINITY_TYPE (thread_num, 'n'),
247 AFFINITY_TYPE (num_threads, 'N'),
248 AFFINITY_TYPE (ancestor_tnum, 'a'),
249 AFFINITY_TYPE (host, 'H'),
250 AFFINITY_TYPE (process_id, 'P'),
251 AFFINITY_TYPE (native_thread_id, 'i'),
252 AFFINITY_TYPE (thread_affinity, 'A')
253 #undef AFFINITY_TYPE
256 size_t
257 gomp_display_affinity (char *buffer, size_t size,
258 const char *format, gomp_thread_handle handle,
259 struct gomp_team_state *ts, unsigned int place)
261 size_t ret = 0;
264 const char *p = strchr (format, '%');
265 bool zero = false;
266 bool right = false;
267 size_t sz = -1;
268 char c;
269 int val;
270 if (p == NULL)
271 p = strchr (format, '\0');
272 if (p != format)
273 gomp_display_string (buffer, size, &ret,
274 format, p - format);
275 if (*p == '\0')
276 break;
277 p++;
278 if (*p == '%')
280 gomp_display_string (buffer, size, &ret, "%", 1);
281 format = p + 1;
282 continue;
284 if (*p == '0')
286 zero = true;
287 p++;
288 if (*p != '.')
289 gomp_fatal ("leading zero not followed by dot in affinity format");
291 if (*p == '.')
293 right = true;
294 p++;
296 if (*p >= '1' && *p <= '9')
298 char *end;
299 sz = strtoul (p, &end, 10);
300 p = end;
302 else if (zero || right)
303 gomp_fatal ("leading zero or right justification in affinity format "
304 "requires size");
305 c = *p;
306 if (c == '{')
308 int i;
309 for (i = 0;
310 i < sizeof (affinity_types) / sizeof (affinity_types[0]); ++i)
311 if (strncmp (p + 1, affinity_types[i].long_str,
312 affinity_types[i].long_len) == 0
313 && p[affinity_types[i].long_len + 1] == '}')
315 c = affinity_types[i].short_c;
316 p += affinity_types[i].long_len + 1;
317 break;
319 if (c == '{')
321 char *q = strchr (p + 1, '}');
322 if (q)
323 gomp_fatal ("unsupported long type name '%.*s' in affinity "
324 "format", (int) (q - (p + 1)), p + 1);
325 else
326 gomp_fatal ("unterminated long type name '%s' in affinity "
327 "format", p + 1);
330 switch (c)
332 case 't':
333 val = omp_get_team_num ();
334 goto do_int;
335 case 'T':
336 val = omp_get_num_teams ();
337 goto do_int;
338 case 'L':
339 val = ts->level;
340 goto do_int;
341 case 'n':
342 val = ts->team_id;
343 goto do_int;
344 case 'N':
345 val = ts->team ? ts->team->nthreads : 1;
346 goto do_int;
347 case 'a':
348 val = ts->team ? ts->team->prev_ts.team_id : -1;
349 goto do_int;
350 case 'H':
351 gomp_display_hostname (buffer, size, &ret, right, sz);
352 break;
353 case 'P':
354 #ifdef HAVE_GETPID
355 val = getpid ();
356 #else
357 val = 0;
358 #endif
359 goto do_int;
360 case 'i':
361 #if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__)
363 char buf[3 * (sizeof (handle) + sizeof (uintptr_t) + sizeof (int))
364 + 4];
365 /* This macro returns expr unmodified for integral or pointer
366 types and 0 for anything else (e.g. aggregates). */
367 #define gomp_nonaggregate(expr) \
368 __builtin_choose_expr (__builtin_classify_type (expr) == 1 \
369 || __builtin_classify_type (expr) == 5, expr, 0)
370 /* This macro returns expr unmodified for integral types,
371 (uintptr_t) (expr) for pointer types and 0 for anything else
372 (e.g. aggregates). */
373 #define gomp_integral(expr) \
374 __builtin_choose_expr (__builtin_classify_type (expr) == 5, \
375 (uintptr_t) gomp_nonaggregate (expr), \
376 gomp_nonaggregate (expr))
378 if (sizeof (gomp_integral (handle)) == sizeof (unsigned long))
379 sprintf (buf, "0x%lx", (unsigned long) gomp_integral (handle));
380 #if defined (HAVE_INTTYPES_H) && defined (PRIx64)
381 else if (sizeof (gomp_integral (handle)) == sizeof (uint64_t))
382 sprintf (buf, "0x%" PRIx64, (uint64_t) gomp_integral (handle));
383 #else
384 else if (sizeof (gomp_integral (handle))
385 == sizeof (unsigned long long))
386 sprintf (buf, "0x%llx",
387 (unsigned long long) gomp_integral (handle));
388 #endif
389 else
390 sprintf (buf, "0x%x", (unsigned int) gomp_integral (handle));
391 gomp_display_num (buffer, size, &ret, zero, right, sz, buf);
392 break;
394 #else
395 val = 0;
396 goto do_int;
397 #endif
398 case 'A':
399 if (sz == (size_t) -1)
400 gomp_display_affinity_place (buffer, size, &ret,
401 place - 1);
402 else if (right)
404 size_t len = 0;
405 gomp_display_affinity_place (NULL, 0, &len, place - 1);
406 if (len < sz)
407 gomp_display_repeat (buffer, size, &ret, ' ', sz - len);
408 gomp_display_affinity_place (buffer, size, &ret, place - 1);
410 else
412 size_t start = ret;
413 gomp_display_affinity_place (buffer, size, &ret, place - 1);
414 if (ret - start < sz)
415 gomp_display_repeat (buffer, size, &ret, ' ', sz - (ret - start));
417 break;
418 do_int:
419 gomp_display_int (buffer, size, &ret, zero, right, sz, val);
420 break;
421 default:
422 gomp_fatal ("unsupported type %c in affinity format", c);
424 format = p + 1;
426 while (1);
427 return ret;
430 size_t
431 omp_capture_affinity (char *buffer, size_t size, const char *format)
433 struct gomp_thread *thr = gomp_thread ();
434 size_t ret
435 = gomp_display_affinity (buffer, size,
436 format && *format
437 ? format : gomp_affinity_format_var,
438 gomp_thread_self (), &thr->ts, thr->place);
439 if (size)
441 if (ret >= size)
442 buffer[size - 1] = '\0';
443 else
444 buffer[ret] = '\0';
446 return ret;
448 ialias (omp_capture_affinity)
450 void
451 omp_display_affinity (const char *format)
453 char buf[512];
454 char *b;
455 size_t ret = ialias_call (omp_capture_affinity) (buf, sizeof buf, format);
456 if (ret < sizeof buf)
458 buf[ret] = '\n';
459 fwrite (buf, 1, ret + 1, stderr);
460 return;
462 b = gomp_malloc (ret + 1);
463 ialias_call (omp_capture_affinity) (b, ret + 1, format);
464 b[ret] = '\n';
465 fwrite (b, 1, ret + 1, stderr);
466 free (b);
469 void
470 gomp_display_affinity_thread (gomp_thread_handle handle,
471 struct gomp_team_state *ts, unsigned int place)
473 char buf[512];
474 char *b;
475 size_t ret = gomp_display_affinity (buf, sizeof buf, gomp_affinity_format_var,
476 handle, ts, place);
477 if (ret < sizeof buf)
479 buf[ret] = '\n';
480 fwrite (buf, 1, ret + 1, stderr);
481 return;
483 b = gomp_malloc (ret + 1);
484 gomp_display_affinity (b, ret + 1, gomp_affinity_format_var,
485 handle, ts, place);
486 b[ret] = '\n';
487 fwrite (b, 1, ret + 1, stderr);
488 free (b);