3749c3aff6
This patch avoids the following relocations: readelf -Wr libgomp.so.1.0.0 | grep omp_ 00000000000470e0 0000020700000007 R_X86_64_JUMP_SLOT 000000000001d9d0 omp_fulfill_event@@OMP_5.0.1 + 0 0000000000047170 000000b800000007 R_X86_64_JUMP_SLOT 000000000000e760 omp_display_env@@OMP_5.1 + 0 00000000000471e0 000000e800000007 R_X86_64_JUMP_SLOT 000000000000f910 omp_get_initial_device@@OMP_4.5 + 0 0000000000047280 0000019500000007 R_X86_64_JUMP_SLOT 0000000000015940 omp_get_active_level@@OMP_3.0 + 0 00000000000472c8 0000020d00000007 R_X86_64_JUMP_SLOT 0000000000035210 omp_get_team_num@@OMP_4.0 + 0 00000000000472f0 0000014700000007 R_X86_64_JUMP_SLOT 0000000000035200 omp_get_num_teams@@OMP_4.0 + 0 by using ialias{,_call,_redirect} macros as needed. We still have many acc_* PLT relocations, could somebody please fix those? readelf -Wr libgomp.so.1.0.0 | grep acc_ 0000000000046fb8 000001ed00000006 R_X86_64_GLOB_DAT 0000000000036350 acc_prof_unregister@@OACC_2.5.1 + 0 0000000000046fd8 000000a400000006 R_X86_64_GLOB_DAT 0000000000035f30 acc_prof_register@@OACC_2.5.1 + 0 0000000000046fe0 000001d100000006 R_X86_64_GLOB_DAT 0000000000035ee0 acc_prof_lookup@@OACC_2.5.1 + 0 0000000000047058 000001dd00000007 R_X86_64_JUMP_SLOT 0000000000031f40 acc_create_async@@OACC_2.5 + 0 0000000000047068 0000011500000007 R_X86_64_JUMP_SLOT 000000000002fc60 acc_get_property@@OACC_2.6 + 0 0000000000047070 000001fb00000007 R_X86_64_JUMP_SLOT 0000000000032ce0 acc_wait_all@@OACC_2.0 + 0 0000000000047080 0000006500000007 R_X86_64_JUMP_SLOT 000000000002f990 acc_on_device@@OACC_2.0 + 0 0000000000047088 000000ae00000007 R_X86_64_JUMP_SLOT 0000000000032140 acc_attach_async@@OACC_2.6 + 0 0000000000047090 0000021900000007 R_X86_64_JUMP_SLOT 000000000002f550 acc_get_device_type@@OACC_2.0 + 0 0000000000047098 000001cb00000007 R_X86_64_JUMP_SLOT 0000000000032090 acc_copyout_finalize@@OACC_2.5 + 0 00000000000470a8 0000005200000007 R_X86_64_JUMP_SLOT 0000000000031f80 acc_copyin@@OACC_2.0 + 0 00000000000470b8 000001ad00000007 R_X86_64_JUMP_SLOT 0000000000032030 acc_delete_finalize@@OACC_2.5 + 0 00000000000470e8 0000010900000007 R_X86_64_JUMP_SLOT 0000000000031f00 acc_create@@OACC_2.0 + 0 00000000000470f8 0000005900000007 R_X86_64_JUMP_SLOT 0000000000032b70 acc_wait_async@@OACC_2.0 + 0 0000000000047110 0000013100000007 R_X86_64_JUMP_SLOT 0000000000032860 acc_async_test@@OACC_2.0 + 0 0000000000047118 000001ff00000007 R_X86_64_JUMP_SLOT 000000000002f720 acc_get_device_num@@OACC_2.0 + 0 0000000000047128 0000019100000007 R_X86_64_JUMP_SLOT 0000000000032020 acc_delete_async@@OACC_2.5 + 0 0000000000047130 000001d200000007 R_X86_64_JUMP_SLOT 000000000002efa0 acc_shutdown@@OACC_2.0 + 0 0000000000047150 000000d000000007 R_X86_64_JUMP_SLOT 0000000000031f00 acc_present_or_create@@OACC_2.0 + 0 0000000000047188 0000019200000007 R_X86_64_JUMP_SLOT 0000000000031910 acc_is_present@@OACC_2.0 + 0 0000000000047190 000001aa00000007 R_X86_64_JUMP_SLOT 000000000002fca0 acc_get_property_string@@OACC_2.6 + 0 00000000000471d0 000001bf00000007 R_X86_64_JUMP_SLOT 0000000000032120 acc_update_self_async@@OACC_2.5 + 0 0000000000047200 0000020500000007 R_X86_64_JUMP_SLOT 0000000000032e00 acc_wait_all_async@@OACC_2.0 + 0 0000000000047208 000000a600000007 R_X86_64_JUMP_SLOT 0000000000031790 acc_deviceptr@@OACC_2.0 + 0 0000000000047218 0000007500000007 R_X86_64_JUMP_SLOT 0000000000032000 acc_delete@@OACC_2.0 + 0 0000000000047238 000001e900000007 R_X86_64_JUMP_SLOT 000000000002f3a0 acc_set_device_type@@OACC_2.0 + 0 0000000000047240 000001f600000007 R_X86_64_JUMP_SLOT 000000000002ef20 acc_init@@OACC_2.0 + 0 0000000000047248 0000018800000007 R_X86_64_JUMP_SLOT 0000000000032060 acc_copyout@@OACC_2.0 + 0 0000000000047258 0000021f00000007 R_X86_64_JUMP_SLOT 0000000000032a80 acc_wait@@OACC_2.0 + 0 0000000000047270 000001bc00000007 R_X86_64_JUMP_SLOT 0000000000032100 acc_update_self@@OACC_2.0 + 0 0000000000047288 0000011400000007 R_X86_64_JUMP_SLOT 0000000000032080 acc_copyout_async@@OACC_2.5 + 0 0000000000047290 0000013d00000007 R_X86_64_JUMP_SLOT 000000000002f850 acc_set_device_num@@OACC_2.0 + 0 00000000000472a8 000000c500000007 R_X86_64_JUMP_SLOT 00000000000320e0 acc_update_device_async@@OACC_2.5 + 0 00000000000472c0 0000014600000007 R_X86_64_JUMP_SLOT 0000000000031fc0 acc_copyin_async@@OACC_2.5 + 0 00000000000472f8 0000006a00000007 R_X86_64_JUMP_SLOT 000000000002f310 acc_get_num_devices@@OACC_2.0 + 0 0000000000047350 0000021700000007 R_X86_64_JUMP_SLOT 0000000000031f80 acc_present_or_copyin@@OACC_2.0 + 0 0000000000047360 0000020900000007 R_X86_64_JUMP_SLOT 00000000000320c0 acc_update_device@@OACC_2.0 + 0 0000000000047380 0000008400000007 R_X86_64_JUMP_SLOT 0000000000032950 acc_async_test_all@@OACC_2.0 + 0 2021-10-01 Jakub Jelinek <jakub@redhat.com> * affinity-fmt.c (omp_get_team_num, omp_get_num_teams): Add ialias_redirect. * env.c (handle_omp_display_env): Use ialias_call. * icv-device.c: Move ialias right below each function. (omp_get_device_num): Use ialias_call. * fortran.c (omp_fulfill_event): Add ialias_redirect. * icv.c (omp_get_active_level): Add ialias_redirect.
499 lines
12 KiB
C
499 lines
12 KiB
C
/* Copyright (C) 2018-2021 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
|
|
|
|
ialias_redirect (omp_get_team_num)
|
|
ialias_redirect (omp_get_num_teams)
|
|
|
|
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);
|
|
}
|