Mercurial > hg > CbC > CbC_gcc
diff libgomp/affinity-fmt.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgomp/affinity-fmt.c Thu Feb 13 11:34:05 2020 +0900 @@ -0,0 +1,495 @@ +/* Copyright (C) 2018-2020 Free Software Foundation, Inc. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + This file is part of the GNU Offloading and Multi Processing Library + (libgomp). + + Libgomp is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libgomp.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> /* For PRIx64. */ +#endif +#ifdef HAVE_UNAME +#include <sys/utsname.h> +#endif + +bool +gomp_print_string (const char *str, size_t len) +{ + return fwrite (str, 1, len, stderr) != len; +} + +void +gomp_set_affinity_format (const char *format, size_t len) +{ + if (len < gomp_affinity_format_len) + memcpy (gomp_affinity_format_var, format, len); + else + { + char *p; + if (gomp_affinity_format_len) + p = gomp_realloc (gomp_affinity_format_var, len + 1); + else + p = gomp_malloc (len + 1); + memcpy (p, format, len); + gomp_affinity_format_var = p; + gomp_affinity_format_len = len + 1; + } + gomp_affinity_format_var[len] = '\0'; +} + +void +omp_set_affinity_format (const char *format) +{ + gomp_set_affinity_format (format, strlen (format)); +} + +size_t +omp_get_affinity_format (char *buffer, size_t size) +{ + size_t len = strlen (gomp_affinity_format_var); + if (size) + { + if (len < size) + memcpy (buffer, gomp_affinity_format_var, len + 1); + else + { + memcpy (buffer, gomp_affinity_format_var, size - 1); + buffer[size - 1] = '\0'; + } + } + return len; +} + +void +gomp_display_string (char *buffer, size_t size, size_t *ret, + const char *str, size_t len) +{ + size_t r = *ret; + if (size && r < size) + { + size_t l = len; + if (size - r < len) + l = size - r; + memcpy (buffer + r, str, l); + } + *ret += len; + if (__builtin_expect (r > *ret, 0)) + gomp_fatal ("overflow in omp_capture_affinity"); +} + +static void +gomp_display_repeat (char *buffer, size_t size, size_t *ret, + char c, size_t len) +{ + size_t r = *ret; + if (size && r < size) + { + size_t l = len; + if (size - r < len) + l = size - r; + memset (buffer + r, c, l); + } + *ret += len; + if (__builtin_expect (r > *ret, 0)) + gomp_fatal ("overflow in omp_capture_affinity"); +} + +static void +gomp_display_num (char *buffer, size_t size, size_t *ret, + bool zero, bool right, size_t sz, char *buf) +{ + size_t l = strlen (buf); + if (sz == (size_t) -1 || l >= sz) + { + gomp_display_string (buffer, size, ret, buf, l); + return; + } + if (zero) + { + if (buf[0] == '-') + gomp_display_string (buffer, size, ret, buf, 1); + else if (buf[0] == '0' && buf[1] == 'x') + gomp_display_string (buffer, size, ret, buf, 2); + gomp_display_repeat (buffer, size, ret, '0', sz - l); + if (buf[0] == '-') + gomp_display_string (buffer, size, ret, buf + 1, l - 1); + else if (buf[0] == '0' && buf[1] == 'x') + gomp_display_string (buffer, size, ret, buf + 2, l - 2); + else + gomp_display_string (buffer, size, ret, buf, l); + } + else if (right) + { + gomp_display_repeat (buffer, size, ret, ' ', sz - l); + gomp_display_string (buffer, size, ret, buf, l); + } + else + { + gomp_display_string (buffer, size, ret, buf, l); + gomp_display_repeat (buffer, size, ret, ' ', sz - l); + } +} + +static void +gomp_display_int (char *buffer, size_t size, size_t *ret, + bool zero, bool right, size_t sz, int num) +{ + char buf[3 * sizeof (int) + 2]; + sprintf (buf, "%d", num); + gomp_display_num (buffer, size, ret, zero, right, sz, buf); +} + +static void +gomp_display_string_len (char *buffer, size_t size, size_t *ret, + bool right, size_t sz, char *str, size_t len) +{ + if (sz == (size_t) -1 || len >= sz) + { + gomp_display_string (buffer, size, ret, str, len); + return; + } + + if (right) + { + gomp_display_repeat (buffer, size, ret, ' ', sz - len); + gomp_display_string (buffer, size, ret, str, len); + } + else + { + gomp_display_string (buffer, size, ret, str, len); + gomp_display_repeat (buffer, size, ret, ' ', sz - len); + } +} + +static void +gomp_display_hostname (char *buffer, size_t size, size_t *ret, + bool right, size_t sz) +{ +#ifdef HAVE_GETHOSTNAME + { + char buf[256]; + char *b = buf; + size_t len = 256; + do + { + b[len - 1] = '\0'; + if (gethostname (b, len - 1) == 0) + { + size_t l = strlen (b); + if (l < len - 1) + { + gomp_display_string_len (buffer, size, ret, + right, sz, b, l); + if (b != buf) + free (b); + return; + } + } + if (len == 1048576) + break; + len = len * 2; + if (len == 512) + b = gomp_malloc (len); + else + b = gomp_realloc (b, len); + } + while (1); + if (b != buf) + free (b); + } +#endif +#ifdef HAVE_UNAME + { + struct utsname buf; + if (uname (&buf) == 0) + { + gomp_display_string_len (buffer, size, ret, right, sz, + buf.nodename, strlen (buf.nodename)); + return; + } + } +#endif + gomp_display_string_len (buffer, size, ret, right, sz, "node", 4); +} + +struct affinity_types_struct { + char long_str[18]; + char long_len; + char short_c; }; + +static struct affinity_types_struct affinity_types[] = +{ +#define AFFINITY_TYPE(l, s) \ + { #l, sizeof (#l) - 1, s } + AFFINITY_TYPE (team_num, 't'), + AFFINITY_TYPE (num_teams, 'T'), + AFFINITY_TYPE (nesting_level, 'L'), + AFFINITY_TYPE (thread_num, 'n'), + AFFINITY_TYPE (num_threads, 'N'), + AFFINITY_TYPE (ancestor_tnum, 'a'), + AFFINITY_TYPE (host, 'H'), + AFFINITY_TYPE (process_id, 'P'), + AFFINITY_TYPE (native_thread_id, 'i'), + AFFINITY_TYPE (thread_affinity, 'A') +#undef AFFINITY_TYPE +}; + +size_t +gomp_display_affinity (char *buffer, size_t size, + const char *format, gomp_thread_handle handle, + struct gomp_team_state *ts, unsigned int place) +{ + size_t ret = 0; + do + { + const char *p = strchr (format, '%'); + bool zero = false; + bool right = false; + size_t sz = -1; + char c; + int val; + if (p == NULL) + p = strchr (format, '\0'); + if (p != format) + gomp_display_string (buffer, size, &ret, + format, p - format); + if (*p == '\0') + break; + p++; + if (*p == '%') + { + gomp_display_string (buffer, size, &ret, "%", 1); + format = p + 1; + continue; + } + if (*p == '0') + { + zero = true; + p++; + if (*p != '.') + gomp_fatal ("leading zero not followed by dot in affinity format"); + } + if (*p == '.') + { + right = true; + p++; + } + if (*p >= '1' && *p <= '9') + { + char *end; + sz = strtoul (p, &end, 10); + p = end; + } + else if (zero || right) + gomp_fatal ("leading zero or right justification in affinity format " + "requires size"); + c = *p; + if (c == '{') + { + int i; + for (i = 0; + i < sizeof (affinity_types) / sizeof (affinity_types[0]); ++i) + if (strncmp (p + 1, affinity_types[i].long_str, + affinity_types[i].long_len) == 0 + && p[affinity_types[i].long_len + 1] == '}') + { + c = affinity_types[i].short_c; + p += affinity_types[i].long_len + 1; + break; + } + if (c == '{') + { + char *q = strchr (p + 1, '}'); + if (q) + gomp_fatal ("unsupported long type name '%.*s' in affinity " + "format", (int) (q - (p + 1)), p + 1); + else + gomp_fatal ("unterminated long type name '%s' in affinity " + "format", p + 1); + } + } + switch (c) + { + case 't': + val = omp_get_team_num (); + goto do_int; + case 'T': + val = omp_get_num_teams (); + goto do_int; + case 'L': + val = ts->level; + goto do_int; + case 'n': + val = ts->team_id; + goto do_int; + case 'N': + val = ts->team ? ts->team->nthreads : 1; + goto do_int; + case 'a': + val = ts->team ? ts->team->prev_ts.team_id : -1; + goto do_int; + case 'H': + gomp_display_hostname (buffer, size, &ret, right, sz); + break; + case 'P': +#ifdef HAVE_GETPID + val = getpid (); +#else + val = 0; +#endif + goto do_int; + case 'i': +#if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__) + { + char buf[3 * (sizeof (handle) + sizeof (uintptr_t) + sizeof (int)) + + 4]; + /* This macro returns expr unmodified for integral or pointer + types and 0 for anything else (e.g. aggregates). */ +#define gomp_nonaggregate(expr) \ + __builtin_choose_expr (__builtin_classify_type (expr) == 1 \ + || __builtin_classify_type (expr) == 5, expr, 0) + /* This macro returns expr unmodified for integral types, + (uintptr_t) (expr) for pointer types and 0 for anything else + (e.g. aggregates). */ +#define gomp_integral(expr) \ + __builtin_choose_expr (__builtin_classify_type (expr) == 5, \ + (uintptr_t) gomp_nonaggregate (expr), \ + gomp_nonaggregate (expr)) + + if (sizeof (gomp_integral (handle)) == sizeof (unsigned long)) + sprintf (buf, "0x%lx", (unsigned long) gomp_integral (handle)); +#if defined (HAVE_INTTYPES_H) && defined (PRIx64) + else if (sizeof (gomp_integral (handle)) == sizeof (uint64_t)) + sprintf (buf, "0x%" PRIx64, (uint64_t) gomp_integral (handle)); +#else + else if (sizeof (gomp_integral (handle)) + == sizeof (unsigned long long)) + sprintf (buf, "0x%llx", + (unsigned long long) gomp_integral (handle)); +#endif + else + sprintf (buf, "0x%x", (unsigned int) gomp_integral (handle)); + gomp_display_num (buffer, size, &ret, zero, right, sz, buf); + break; + } +#else + val = 0; + goto do_int; +#endif + case 'A': + if (sz == (size_t) -1) + gomp_display_affinity_place (buffer, size, &ret, + place - 1); + else if (right) + { + size_t len = 0; + gomp_display_affinity_place (NULL, 0, &len, place - 1); + if (len < sz) + gomp_display_repeat (buffer, size, &ret, ' ', sz - len); + gomp_display_affinity_place (buffer, size, &ret, place - 1); + } + else + { + size_t start = ret; + gomp_display_affinity_place (buffer, size, &ret, place - 1); + if (ret - start < sz) + gomp_display_repeat (buffer, size, &ret, ' ', sz - (ret - start)); + } + break; + do_int: + gomp_display_int (buffer, size, &ret, zero, right, sz, val); + break; + default: + gomp_fatal ("unsupported type %c in affinity format", c); + } + format = p + 1; + } + while (1); + return ret; +} + +size_t +omp_capture_affinity (char *buffer, size_t size, const char *format) +{ + struct gomp_thread *thr = gomp_thread (); + size_t ret + = gomp_display_affinity (buffer, size, + format && *format + ? format : gomp_affinity_format_var, + gomp_thread_self (), &thr->ts, thr->place); + if (size) + { + if (ret >= size) + buffer[size - 1] = '\0'; + else + buffer[ret] = '\0'; + } + return ret; +} +ialias (omp_capture_affinity) + +void +omp_display_affinity (const char *format) +{ + char buf[512]; + char *b; + size_t ret = ialias_call (omp_capture_affinity) (buf, sizeof buf, format); + if (ret < sizeof buf) + { + buf[ret] = '\n'; + gomp_print_string (buf, ret + 1); + return; + } + b = gomp_malloc (ret + 1); + ialias_call (omp_capture_affinity) (b, ret + 1, format); + b[ret] = '\n'; + gomp_print_string (b, ret + 1); + free (b); +} + +void +gomp_display_affinity_thread (gomp_thread_handle handle, + struct gomp_team_state *ts, unsigned int place) +{ + char buf[512]; + char *b; + size_t ret = gomp_display_affinity (buf, sizeof buf, gomp_affinity_format_var, + handle, ts, place); + if (ret < sizeof buf) + { + buf[ret] = '\n'; + gomp_print_string (buf, ret + 1); + return; + } + b = gomp_malloc (ret + 1); + gomp_display_affinity (b, ret + 1, gomp_affinity_format_var, + handle, ts, place); + b[ret] = '\n'; + gomp_print_string (b, ret + 1); + free (b); +}