libgomp: Extend OMP_ALLOCATOR, add affinity env var doc
Support OpenMP 5.1's syntax for OMP_ALLOCATOR as well, which permits besides predefined allocators also predefined memspaces optionally followed by traits. Additionally, this commit adds the previously lacking documentation for OMP_ALLOCATOR, OMP_AFFINITY_FORMAT and OMP_DISPLAY_AFFINITY. libgomp/ChangeLog: * env.c (gomp_def_allocator_envvar): New var. (parse_allocator): Handle OpenMP 5.1 syntax. (cleanup_env): New. (omp_display_env): Output gomp_def_allocator_envvar for an allocator with traits. * libgomp.texi (OMP_ALLOCATOR, OMP_AFFINITY_FORMAT, OMP_DISPLAY_AFFINITY): New. * testsuite/libgomp.c/allocator-1.c: New test. * testsuite/libgomp.c/allocator-2.c: New test. * testsuite/libgomp.c/allocator-3.c: New test. * testsuite/libgomp.c/allocator-4.c: New test. * testsuite/libgomp.c/allocator-5.c: New test. * testsuite/libgomp.c/allocator-6.c: New test.
This commit is contained in:
parent
a4df0ce78d
commit
73a0d3bf89
8 changed files with 419 additions and 13 deletions
186
libgomp/env.c
186
libgomp/env.c
|
@ -112,6 +112,7 @@ unsigned long gomp_bind_var_list_len;
|
|||
void **gomp_places_list;
|
||||
unsigned long gomp_places_list_len;
|
||||
uintptr_t gomp_def_allocator = omp_default_mem_alloc;
|
||||
char *gomp_def_allocator_envvar = NULL;
|
||||
int gomp_debug_var;
|
||||
unsigned int gomp_num_teams_var;
|
||||
int gomp_nteams_var;
|
||||
|
@ -1233,8 +1234,12 @@ parse_affinity (bool ignore)
|
|||
static bool
|
||||
parse_allocator (const char *env, const char *val, void *const params[])
|
||||
{
|
||||
const char *orig_val = val;
|
||||
uintptr_t *ret = (uintptr_t *) params[0];
|
||||
*ret = omp_default_mem_alloc;
|
||||
bool memspace = false;
|
||||
size_t ntraits = 0;
|
||||
omp_alloctrait_t *traits;
|
||||
|
||||
if (val == NULL)
|
||||
return false;
|
||||
|
@ -1243,28 +1248,169 @@ parse_allocator (const char *env, const char *val, void *const params[])
|
|||
++val;
|
||||
if (0)
|
||||
;
|
||||
#define C(v) \
|
||||
#define C(v, m) \
|
||||
else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
|
||||
{ \
|
||||
*ret = v; \
|
||||
val += sizeof (#v) - 1; \
|
||||
memspace = m; \
|
||||
}
|
||||
C (omp_default_mem_alloc)
|
||||
C (omp_large_cap_mem_alloc)
|
||||
C (omp_const_mem_alloc)
|
||||
C (omp_high_bw_mem_alloc)
|
||||
C (omp_low_lat_mem_alloc)
|
||||
C (omp_cgroup_mem_alloc)
|
||||
C (omp_pteam_mem_alloc)
|
||||
C (omp_thread_mem_alloc)
|
||||
C (omp_default_mem_alloc, false)
|
||||
C (omp_large_cap_mem_alloc, false)
|
||||
C (omp_const_mem_alloc, false)
|
||||
C (omp_high_bw_mem_alloc, false)
|
||||
C (omp_low_lat_mem_alloc, false)
|
||||
C (omp_cgroup_mem_alloc, false)
|
||||
C (omp_pteam_mem_alloc, false)
|
||||
C (omp_thread_mem_alloc, false)
|
||||
C (omp_default_mem_space, true)
|
||||
C (omp_large_cap_mem_space, true)
|
||||
C (omp_const_mem_space, true)
|
||||
C (omp_high_bw_mem_space, true)
|
||||
C (omp_low_lat_mem_space, true)
|
||||
#undef C
|
||||
else
|
||||
val = "X";
|
||||
goto invalid;
|
||||
if (memspace && *val == ':')
|
||||
{
|
||||
++val;
|
||||
const char *cp = val;
|
||||
while (*cp != '\0')
|
||||
{
|
||||
if (*cp == '=')
|
||||
++ntraits;
|
||||
++cp;
|
||||
}
|
||||
traits = gomp_alloca (ntraits * sizeof (omp_alloctrait_t));
|
||||
size_t n = 0;
|
||||
while (*val != '\0')
|
||||
{
|
||||
#define C(v) \
|
||||
else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
|
||||
{ \
|
||||
val += sizeof (#v); \
|
||||
traits[n].key = omp_atk_ ## v;
|
||||
#define V(v) \
|
||||
else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
|
||||
{ \
|
||||
val += sizeof (#v) - 1; \
|
||||
traits[n].value = omp_atv_ ## v; \
|
||||
}
|
||||
if (0)
|
||||
;
|
||||
C (sync_hint)
|
||||
if (0)
|
||||
;
|
||||
V (contended)
|
||||
V (uncontended)
|
||||
V (serialized)
|
||||
V (private)
|
||||
else
|
||||
goto invalid;
|
||||
}
|
||||
C (alignment)
|
||||
char *end;
|
||||
errno = 0;
|
||||
traits[n].value = strtol (val, &end, 10);
|
||||
if (errno || end == val || traits[n].value <= 0)
|
||||
goto invalid;
|
||||
val = end;
|
||||
}
|
||||
C (access)
|
||||
if (0)
|
||||
;
|
||||
V (all)
|
||||
V (cgroup)
|
||||
V (pteam)
|
||||
V (thread)
|
||||
else
|
||||
goto invalid;
|
||||
}
|
||||
C (pool_size)
|
||||
char *end;
|
||||
errno = 0;
|
||||
traits[n].value = strtol (val, &end, 10);
|
||||
if (errno || end == val || traits[n].value <= 0)
|
||||
goto invalid;
|
||||
val = end;
|
||||
}
|
||||
C (fallback)
|
||||
if (0)
|
||||
;
|
||||
V (default_mem_fb)
|
||||
V (null_fb)
|
||||
V (abort_fb)
|
||||
V (allocator_fb)
|
||||
else
|
||||
goto invalid;
|
||||
}
|
||||
/* Ignore fb_data, which expects an allocator handle. */
|
||||
C (pinned)
|
||||
if (0)
|
||||
;
|
||||
V (true)
|
||||
V (false)
|
||||
else
|
||||
goto invalid;
|
||||
}
|
||||
C (partition)
|
||||
if (0)
|
||||
;
|
||||
V (environment)
|
||||
V (nearest)
|
||||
V (blocked)
|
||||
V (interleaved)
|
||||
else
|
||||
goto invalid;
|
||||
}
|
||||
else
|
||||
goto invalid;
|
||||
if (*val != ',')
|
||||
break;
|
||||
++val;
|
||||
++n;
|
||||
if (*val == '\0')
|
||||
goto invalid;
|
||||
}
|
||||
#undef C
|
||||
#undef V
|
||||
}
|
||||
else if (memspace)
|
||||
switch (*ret)
|
||||
{
|
||||
case omp_default_mem_space: *ret = omp_default_mem_alloc; break;
|
||||
case omp_large_cap_mem_space: *ret = omp_large_cap_mem_alloc; break;
|
||||
case omp_const_mem_space: *ret = omp_const_mem_alloc; break;
|
||||
case omp_high_bw_mem_space: *ret = omp_high_bw_mem_alloc; break;
|
||||
case omp_low_lat_mem_space: *ret = omp_low_lat_mem_alloc; break;
|
||||
default: __builtin_unreachable ();
|
||||
}
|
||||
while (isspace ((unsigned char) *val))
|
||||
++val;
|
||||
if (*val == '\0')
|
||||
return true;
|
||||
print_env_var_error (env, val);
|
||||
{
|
||||
if (ntraits)
|
||||
{
|
||||
*ret = omp_init_allocator (*ret, ntraits, traits);
|
||||
if (*ret == omp_null_allocator)
|
||||
{
|
||||
gomp_error ("Allocator of environment variable %.*s cannot be "
|
||||
"created, using omp_default_mem_alloc instead",
|
||||
(int) (orig_val - env - 1), env);
|
||||
*ret = omp_default_mem_alloc;
|
||||
}
|
||||
else
|
||||
gomp_def_allocator_envvar = strdup (orig_val);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
invalid:
|
||||
int len = (orig_val - env - 1);
|
||||
if (*val == '\0')
|
||||
gomp_error ("Missing value at the end of environment variable %s", env);
|
||||
else
|
||||
gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
|
||||
len, env, val);
|
||||
*ret = omp_default_mem_alloc;
|
||||
return false;
|
||||
}
|
||||
|
@ -1784,7 +1930,11 @@ omp_display_env (int verbose)
|
|||
C (omp_pteam_mem_alloc)
|
||||
C (omp_thread_mem_alloc)
|
||||
#undef C
|
||||
default: break;
|
||||
/* For an OMP_ALLOCATOR with traits, '' will be output. */
|
||||
default:
|
||||
if (gomp_def_allocator_envvar)
|
||||
fputs (gomp_def_allocator_envvar, stderr);
|
||||
break;
|
||||
}
|
||||
fputs ("'\n", stderr);
|
||||
|
||||
|
@ -2036,6 +2186,16 @@ startswith (const char *str, const char *prefix)
|
|||
return strncmp (str, prefix, strlen (prefix)) == 0;
|
||||
}
|
||||
|
||||
static void __attribute__((destructor))
|
||||
cleanup_env (void)
|
||||
{
|
||||
if (gomp_def_allocator_envvar != NULL)
|
||||
{
|
||||
free (gomp_def_allocator_envvar);
|
||||
omp_destroy_allocator (gomp_def_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((constructor))
|
||||
initialize_env (void)
|
||||
{
|
||||
|
|
|
@ -1937,7 +1937,10 @@ section 4 of the OpenMP specification in version 4.5, while those
|
|||
beginning with @env{GOMP_} are GNU extensions.
|
||||
|
||||
@menu
|
||||
* OMP_ALLOCATOR:: Set the default allocator
|
||||
* OMP_AFFINITY_FORMAT:: Set the format string used for affinity display
|
||||
* OMP_CANCELLATION:: Set whether cancellation is activated
|
||||
* OMP_DISPLAY_AFFINITY:: Display thread affinity information
|
||||
* OMP_DISPLAY_ENV:: Show OpenMP version and environment variables
|
||||
* OMP_DEFAULT_DEVICE:: Set the device used in target regions
|
||||
* OMP_DYNAMIC:: Dynamic adjustment of threads
|
||||
|
@ -1962,6 +1965,125 @@ beginning with @env{GOMP_} are GNU extensions.
|
|||
@end menu
|
||||
|
||||
|
||||
@node OMP_ALLOCATOR
|
||||
@section @env{OMP_ALLOCATOR} -- Set the default allocator
|
||||
@cindex Environment Variable
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
Sets the default allocator that is used when no allocator has been specified
|
||||
in the @code{allocate} or @code{allocator} clause or if an OpenMP memory
|
||||
routine is invoked with the @code{omp_null_allocator} allocator.
|
||||
If unset, @code{omp_default_mem_alloc} is used.
|
||||
|
||||
The value can either be a predefined allocator or a predefined memory space
|
||||
or a predefined memory space followed by a colon and a comma-separated list
|
||||
of memory trait and value pairs, separated by @code{=}.
|
||||
|
||||
@multitable @columnfractions .45 .45
|
||||
@headitem Predefined allocators @tab Predefined memory spaces
|
||||
@item omp_default_mem_alloc @tab omp_default_mem_space
|
||||
@item omp_large_cap_mem_alloc @tab omp_large_cap_mem_space
|
||||
@item omp_const_mem_alloc @tab omp_const_mem_space
|
||||
@item omp_high_bw_mem_alloc @tab omp_high_bw_mem_space
|
||||
@item omp_low_lat_mem_alloc @tab omp_low_lat_mem_space
|
||||
@item omp_cgroup_mem_alloc @tab --
|
||||
@item omp_pteam_mem_alloc @tab --
|
||||
@item omp_thread_mem_alloc @tab --
|
||||
@end multitable
|
||||
|
||||
@multitable @columnfractions .30 .60
|
||||
@headitem Trait @tab Allowed values
|
||||
@item @code{sync_hint} @tab @code{contended}, @code{uncontended},
|
||||
@code{serialized}, @code{private}
|
||||
@item @code{alignment} @tab Positive integer being a power of two
|
||||
@item @code{access} @tab @code{all}, @code{cgroup},
|
||||
@code{pteam}, @code{thread}
|
||||
@item @code{pool_size} @tab Positive integer
|
||||
@item @code{fallback} @tab @code{default_mem_fb}, @code{null_fb},
|
||||
@code{abort_fb}, @code{allocator_fb}
|
||||
@item @code{fb_data} @tab @emph{unsupported as it needs an allocator handle}
|
||||
@item @code{pinned} @tab @code{true}, @code{false}
|
||||
@item @code{partition} @tab @code{environment}, @code{nearest},
|
||||
@code{blocked}, @code{interleaved}
|
||||
@end multitable
|
||||
|
||||
Examples:
|
||||
@smallexample
|
||||
OMP_ALLOCATOR=omp_high_bw_mem_alloc
|
||||
OMP_ALLOCATOR=omp_large_cap_mem_space
|
||||
OMP_ALLOCATR=omp_low_lat_mem_space:pinned=true,partition=nearest
|
||||
@end smallexample
|
||||
|
||||
@c @item @emph{See also}:
|
||||
|
||||
@item @emph{Reference}:
|
||||
@uref{https://www.openmp.org, OpenMP specification v5.0}, Section 6.21
|
||||
@end table
|
||||
|
||||
|
||||
|
||||
@node OMP_AFFINITY_FORMAT
|
||||
@section @env{OMP_AFFINITY_FORMAT} -- Set the format string used for affinity display
|
||||
@cindex Environment Variable
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
Sets the format string used when displaying OpenMP thread affinity information.
|
||||
Special values are output using @code{%} followed by an optional size
|
||||
specification and then either the single-character field type or its long
|
||||
name enclosed in curly braces; using @code{%%} will display a literal percent.
|
||||
The size specification consists of an optional @code{0.} or @code{.} followed
|
||||
by a positive integer, specifing the minimal width of the output. With
|
||||
@code{0.} and numerical values, the output is padded with zeros on the left;
|
||||
with @code{.}, the output is padded by spaces on the left; otherwise, the
|
||||
output is padded by spaces on the right. If unset, the value is
|
||||
``@code{level %L thread %i affinity %A}''.
|
||||
|
||||
Supported field types are:
|
||||
|
||||
@multitable @columnfractions .10 .25 .60
|
||||
@item t @tab team_num @tab value returned by @code{omp_get_team_num}
|
||||
@item T @tab num_teams @tab value returned by @code{omp_get_num_teams}
|
||||
@item L @tab nesting_level @tab value returned by @code{omp_get_level}
|
||||
@item n @tab thread_num @tab value returned by @code{omp_get_thread_num}
|
||||
@item N @tab num_threads @tab value returned by @code{omp_get_num_threads}
|
||||
@item a @tab ancestor_tnum
|
||||
@tab value returned by
|
||||
@code{omp_get_ancestor_thread_num(omp_get_level()-1)}
|
||||
@item H @tab host @tab name of the host that executes the thread
|
||||
@item P @tab process_id @tab process identifier
|
||||
@item i @tab native_thread_id @tab native thread identifier
|
||||
@item A @tab thread_affinity
|
||||
@tab comma separated list of integer values or ranges, representing the
|
||||
processors on which a process might execute, subject to affinity
|
||||
mechanisms
|
||||
@end multitable
|
||||
|
||||
For instance, after setting
|
||||
|
||||
@smallexample
|
||||
OMP_AFFINITY_FORMAT="%0.2a!%n!%.4L!%N;%.2t;%0.2T;%@{team_num@};%@{num_teams@};%A"
|
||||
@end smallexample
|
||||
|
||||
with either @code{OMP_DISPLAY_AFFINITY} being set or when calling
|
||||
@code{omp_display_affinity} with @code{NULL} or an empty string, the program
|
||||
might display the following:
|
||||
|
||||
@smallexample
|
||||
00!0! 1!4; 0;01;0;1;0-11
|
||||
00!3! 1!4; 0;01;0;1;0-11
|
||||
00!2! 1!4; 0;01;0;1;0-11
|
||||
00!1! 1!4; 0;01;0;1;0-11
|
||||
@end smallexample
|
||||
|
||||
@item @emph{See also}:
|
||||
@ref{OMP_DISPLAY_AFFINITY}
|
||||
|
||||
@item @emph{Reference}:
|
||||
@uref{https://www.openmp.org, OpenMP specification v5.0}, Section 6.14
|
||||
@end table
|
||||
|
||||
|
||||
|
||||
@node OMP_CANCELLATION
|
||||
@section @env{OMP_CANCELLATION} -- Set whether cancellation is activated
|
||||
@cindex Environment Variable
|
||||
|
@ -1979,6 +2101,26 @@ if unset, cancellation is disabled and the @code{cancel} construct is ignored.
|
|||
|
||||
|
||||
|
||||
@node OMP_DISPLAY_AFFINITY
|
||||
@section @env{OMP_DISPLAY_AFFINITY} -- Display thread affinity information
|
||||
@cindex Environment Variable
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
If set to @code{FALSE} or if unset, affinity displaying is disabled.
|
||||
If set to @code{TRUE}, the runtime will display affinity information about
|
||||
OpenMP threads in a parallel region upon entering the region and every time
|
||||
any change occurs.
|
||||
|
||||
@item @emph{See also}:
|
||||
@ref{OMP_AFFINITY_FORMAT}
|
||||
|
||||
@item @emph{Reference}:
|
||||
@uref{https://www.openmp.org, OpenMP specification v5.0}, Section 6.13
|
||||
@end table
|
||||
|
||||
|
||||
|
||||
|
||||
@node OMP_DISPLAY_ENV
|
||||
@section @env{OMP_DISPLAY_ENV} -- Show OpenMP version and environment variables
|
||||
@cindex Environment Variable
|
||||
|
|
15
libgomp/testsuite/libgomp.c/allocator-1.c
Normal file
15
libgomp/testsuite/libgomp.c/allocator-1.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-set-target-env-var OMP_ALLOCATOR "omp_large_cap_mem_alloc" } */
|
||||
/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
|
||||
|
||||
/* { dg-output ".\\\[host\\\] OMP_ALLOCATOR = 'omp_large_cap_mem_alloc'.*" } */
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_allocator_handle_t m = omp_get_default_allocator ();
|
||||
if (m != omp_large_cap_mem_alloc)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
17
libgomp/testsuite/libgomp.c/allocator-2.c
Normal file
17
libgomp/testsuite/libgomp.c/allocator-2.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* { dg-set-target-env-var OMP_ALLOCATOR "omp_large_cap_mem_space" } */
|
||||
/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
|
||||
|
||||
/* Expect omp_large_cap_mem_alloc as allocator for omp_large_cap_mem_space. */
|
||||
/* { dg-output ".\\\[host\\\] OMP_ALLOCATOR = 'omp_large_cap_mem_alloc'.*" } */
|
||||
#include <omp.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_allocator_handle_t m = omp_get_default_allocator ();
|
||||
/* Without traits, omp_large_cap_mem_space implies
|
||||
omp_large_cap_mem_alloc. */
|
||||
if (m != omp_large_cap_mem_alloc)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
27
libgomp/testsuite/libgomp.c/allocator-3.c
Normal file
27
libgomp/testsuite/libgomp.c/allocator-3.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* { dg-set-target-env-var OMP_ALLOCATOR " omp_default_mem_space:alignment=512,pinned=false,access=all " } */
|
||||
/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
|
||||
|
||||
/* We copied the environment string; hence, it may contain white space. */
|
||||
/* { dg-output ".\\\[host\\\] OMP_ALLOCATOR = ' omp_default_mem_space:alignment=512,pinned=false,access=all '.*" } */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <omp.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int *a, *b;
|
||||
a = omp_alloc (sizeof (int) * 1024, omp_null_allocator);
|
||||
|
||||
omp_allocator_handle_t m = omp_get_default_allocator ();
|
||||
b = omp_alloc (sizeof (int) * 1024, m);
|
||||
|
||||
if ((uintptr_t) a % 512 != 0)
|
||||
__builtin_abort ();
|
||||
|
||||
if ((uintptr_t) b % 512 != 0)
|
||||
__builtin_abort ();
|
||||
omp_free (a, omp_null_allocator);
|
||||
omp_free (b, m);
|
||||
return 0;
|
||||
}
|
15
libgomp/testsuite/libgomp.c/allocator-4.c
Normal file
15
libgomp/testsuite/libgomp.c/allocator-4.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-set-target-env-var OMP_ALLOCATOR "omp_const_mem_space:alignment=3,pinned=" } */
|
||||
|
||||
/* { dg-output ".*libgomp: Missing value at the end of environment variable OMP_ALLOCATOR=omp_const_mem_space:alignment=3,pinned=.*" } */
|
||||
/* OMP_ALLOCATOR syntax error -> use omp_default_mem_alloc. */
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_allocator_handle_t m = omp_get_default_allocator ();
|
||||
if (m != omp_default_mem_alloc)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
15
libgomp/testsuite/libgomp.c/allocator-5.c
Normal file
15
libgomp/testsuite/libgomp.c/allocator-5.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-set-target-env-var OMP_ALLOCATOR "omp_const_mem_space:access=none,pinned=false" } */
|
||||
|
||||
/* { dg-output ".*libgomp: Invalid value for environment variable OMP_ALLOCATOR when parsing: none,pinned=false.*" } */
|
||||
/* OMP_ALLOCATOR syntax error -> use omp_default_mem_alloc. */
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_allocator_handle_t m = omp_get_default_allocator ();
|
||||
if (m != omp_default_mem_alloc)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
15
libgomp/testsuite/libgomp.c/allocator-6.c
Normal file
15
libgomp/testsuite/libgomp.c/allocator-6.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-set-target-env-var OMP_ALLOCATOR "omp_default_mem_space:alignment=3" } */
|
||||
|
||||
/* { dg-output ".*libgomp: Allocator of environment variable OMP_ALLOCATOR cannot be created, using omp_default_mem_alloc instead.*" } */
|
||||
/* OMP_ALLOCATOR's alignment is not power of 2 -> use omp_default_mem_alloc. */
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_allocator_handle_t m = omp_get_default_allocator ();
|
||||
if (m != omp_default_mem_alloc)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue