From: Jakub Jelinek Date: Fri, 27 Jul 2018 12:55:28 +0000 (+0200) Subject: libgomp.map (OMP_5.0): Export omp_pause_resource{,_all}{,_}. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9eb83516f43c5df77bdad7de9acc6d0e135020a;p=thirdparty%2Fgcc.git libgomp.map (OMP_5.0): Export omp_pause_resource{,_all}{,_}. * libgomp.map (OMP_5.0): Export omp_pause_resource{,_all}{,_}. * omp.h.in (omp_pause_resource_t): New typedef. (omp_pause_resource, omp_pause_resource_all): New prototypes. * omp_lib.f90.in (omp_pause_resource_kind, omp_pause_soft, omp_pause_hard): New parameters. (omp_pause_resource, omp_pause_resource_all): New interfaces. * omp_lib.h.in (omp_pause_resource_kind, omp_pause_soft, omp_pause_hard): New parameters. (omp_pause_resource, omp_pause_resource_all): New externals. * libgomp.h (gomp_pause_host): New prototype. * team.c (gomp_thread_attr): Remove comment. (gomp_thread_start): Call pthread_detach. (gomp_free_pool_helper): Likewise. (gomp_team_start): Don't call pthread_attr_setdetachstate. (gomp_pause_pool_helper, gomp_pause_host): New functions. * target.c (omp_pause_resource, omp_pause_resource_all): New functions. * env.c (initialize_env): Don't call pthread_attr_setdetachstate. * fortran.c (omp_pause_resource, omp_pause_resource_all): Add ialias_redirect. (omp_pause_resource_, omp_pause_resource_all_): New functions. * config/nvptx/team.c (gomp_pause_host): New function. * config/nvptx/target.c (omp_pause_resource, omp_pause_resource_all): New functions. * testsuite/libgomp.c-c++-common/pause-1.c: New test. * testsuite/libgomp.c-c++-common/pause-2.c: New test. From-SVN: r263029 --- diff --git a/libgomp/ChangeLog.gomp b/libgomp/ChangeLog.gomp index 11276b1be27c..4c04a388e052 100644 --- a/libgomp/ChangeLog.gomp +++ b/libgomp/ChangeLog.gomp @@ -1,3 +1,31 @@ +2018-07-27 Jakub Jelinek + + * libgomp.map (OMP_5.0): Export omp_pause_resource{,_all}{,_}. + * omp.h.in (omp_pause_resource_t): New typedef. + (omp_pause_resource, omp_pause_resource_all): New prototypes. + * omp_lib.f90.in (omp_pause_resource_kind, omp_pause_soft, + omp_pause_hard): New parameters. + (omp_pause_resource, omp_pause_resource_all): New interfaces. + * omp_lib.h.in (omp_pause_resource_kind, omp_pause_soft, + omp_pause_hard): New parameters. + (omp_pause_resource, omp_pause_resource_all): New externals. + * libgomp.h (gomp_pause_host): New prototype. + * team.c (gomp_thread_attr): Remove comment. + (gomp_thread_start): Call pthread_detach. + (gomp_free_pool_helper): Likewise. + (gomp_team_start): Don't call pthread_attr_setdetachstate. + (gomp_pause_pool_helper, gomp_pause_host): New functions. + * target.c (omp_pause_resource, omp_pause_resource_all): New functions. + * env.c (initialize_env): Don't call pthread_attr_setdetachstate. + * fortran.c (omp_pause_resource, omp_pause_resource_all): Add + ialias_redirect. + (omp_pause_resource_, omp_pause_resource_all_): New functions. + * config/nvptx/team.c (gomp_pause_host): New function. + * config/nvptx/target.c (omp_pause_resource, omp_pause_resource_all): + New functions. + * testsuite/libgomp.c-c++-common/pause-1.c: New test. + * testsuite/libgomp.c-c++-common/pause-2.c: New test. + 2018-07-25 Jakub Jelinek * Makefile.am (libgomp_la_SOURCES): Add teams.c. diff --git a/libgomp/config/nvptx/target.c b/libgomp/config/nvptx/target.c index 64004acb422f..3878227a27fa 100644 --- a/libgomp/config/nvptx/target.c +++ b/libgomp/config/nvptx/target.c @@ -47,3 +47,21 @@ GOMP_teams (unsigned int num_teams, unsigned int thread_limit) } gomp_num_teams_var = num_teams - 1; } + +int +omp_pause_resource (omp_pause_resource_t kind, int device_num) +{ + (void) kind; + (void) device_num; + return -1; +} + +int +omp_pause_resource_all (omp_pause_resource_t kind) +{ + (void) kind; + return -1; +} + +ialias (omp_pause_resource) +ialias (omp_pause_resource_all) diff --git a/libgomp/config/nvptx/team.c b/libgomp/config/nvptx/team.c index 34059d389f2e..25859fbc6767 100644 --- a/libgomp/config/nvptx/team.c +++ b/libgomp/config/nvptx/team.c @@ -174,5 +174,11 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, gomp_simple_barrier_wait (&pool->threads_dock); } +int +gomp_pause_host (void) +{ + return -1; +} + #include "../../team.c" #endif diff --git a/libgomp/env.c b/libgomp/env.c index 9f884a8ecd91..d37225d41c0e 100644 --- a/libgomp/env.c +++ b/libgomp/env.c @@ -1348,7 +1348,6 @@ initialize_env (void) /* Not strictly environment related, but ordering constructors is tricky. */ pthread_attr_init (&gomp_thread_attr); - pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED); if (parse_stacksize ("OMP_STACKSIZE", &stacksize) || parse_stacksize ("GOMP_STACKSIZE", &stacksize) diff --git a/libgomp/fortran.c b/libgomp/fortran.c index df2b108968ab..5c2cb03662d8 100644 --- a/libgomp/fortran.c +++ b/libgomp/fortran.c @@ -84,6 +84,8 @@ ialias_redirect (omp_get_team_num) ialias_redirect (omp_is_initial_device) ialias_redirect (omp_get_initial_device) ialias_redirect (omp_get_max_task_priority) +ialias_redirect (omp_pause_resource) +ialias_redirect (omp_pause_resource_all) #endif #ifndef LIBGOMP_GNU_SYMBOL_VERSIONING @@ -659,3 +661,15 @@ omp_capture_affinity_ (char *buffer, const char *format, memset (buffer + ret, ' ', buffer_len - ret); return ret; } + +int32_t +omp_pause_resource_ (const int32_t *kind, const int32_t *device_num) +{ + return omp_pause_resource (*kind, *device_num); +} + +int32_t +omp_pause_resource_all_ (const int32_t *kind) +{ + return omp_pause_resource_all (*kind); +} diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index b0fb6aa4b010..7453d6292c81 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -821,6 +821,7 @@ extern void gomp_team_start (void (*) (void *), void *, unsigned, unsigned, struct gomp_team *); extern void gomp_team_end (void); extern void gomp_free_thread (void *); +extern int gomp_pause_host (void); /* target.c */ diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map index 69faa7fa0310..c8f08e7bf4bb 100644 --- a/libgomp/libgomp.map +++ b/libgomp/libgomp.map @@ -174,6 +174,10 @@ OMP_5.0 { omp_get_affinity_format_; omp_set_affinity_format; omp_set_affinity_format_; + omp_pause_resource; + omp_pause_resource_; + omp_pause_resource_all; + omp_pause_resource_all_; } OMP_4.5; GOMP_1.0 { diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in index 3d350dd089b0..a9fbd9ec1ce5 100644 --- a/libgomp/omp.h.in +++ b/libgomp/omp.h.in @@ -83,6 +83,12 @@ typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t char __omp_depend_t__[2 * sizeof (void *)]; } omp_depend_t; +typedef enum omp_pause_resource_t +{ + omp_pause_soft = 1, + omp_pause_hard = 2 +} omp_pause_resource_t; + #ifdef __cplusplus extern "C" { # define __GOMP_NOTHROW throw () @@ -178,6 +184,9 @@ extern void omp_display_affinity (const char *) __GOMP_NOTHROW; extern __SIZE_TYPE__ omp_capture_affinity (char *, __SIZE_TYPE__, const char *) __GOMP_NOTHROW; +extern int omp_pause_resource (omp_pause_resource_t, int) __GOMP_NOTHROW; +extern int omp_pause_resource_all (omp_pause_resource_t) __GOMP_NOTHROW; + #ifdef __cplusplus } #endif diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in index 8613d17bad69..caecfba749dd 100644 --- a/libgomp/omp_lib.f90.in +++ b/libgomp/omp_lib.f90.in @@ -30,6 +30,7 @@ integer, parameter :: omp_sched_kind = 4 integer, parameter :: omp_proc_bind_kind = 4 integer, parameter :: omp_lock_hint_kind = 4 + integer, parameter :: omp_pause_resource_kind = 4 integer (omp_sched_kind), parameter :: omp_sched_static = 1 integer (omp_sched_kind), parameter :: omp_sched_dynamic = 2 integer (omp_sched_kind), parameter :: omp_sched_guided = 3 @@ -54,6 +55,10 @@ parameter :: omp_lock_hint_nonspeculative = 4 integer (omp_lock_hint_kind), & parameter :: omp_lock_hint_speculative = 8 + integer (kind=omp_pause_resource_kind), & + parameter :: omp_pause_soft = 1 + integer (kind=omp_pause_resource_kind), & + parameter :: omp_pause_hard = 2 end module module omp_lib @@ -460,4 +465,23 @@ end function omp_capture_affinity end interface + interface + function omp_pause_resource (kind, device_num) + use omp_lib_kinds + integer (4) :: omp_pause_resource + integer (kind=omp_pause_resource_kind), & + intent(in) :: kind + integer (4) :: device_num + end function + end interface + + interface + function omp_pause_resource_all (kind) + use omp_lib_kinds + integer (4) :: omp_pause_resource_all + integer (kind=omp_pause_resource_kind), & + intent(in) :: kind + end function + end interface + end module omp_lib diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in index 130fb034eb0c..2a553435a451 100644 --- a/libgomp/omp_lib.h.in +++ b/libgomp/omp_lib.h.in @@ -59,6 +59,12 @@ parameter (omp_lock_hint_nonspeculative = 4) parameter (omp_lock_hint_speculative = 8) parameter (openmp_version = 201511) + integer omp_pause_resource_kind + parameter (omp_pause_resource_kind = 4) + integer (omp_pause_resource_kind) omp_pause_soft + integer (omp_pause_resource_kind) omp_pause_hard + parameter (omp_pause_soft = 1) + parameter (omp_pause_hard = 2) external omp_init_lock, omp_init_nest_lock external omp_init_lock_with_hint @@ -131,3 +137,7 @@ external omp_display_affinity, omp_capture_affinity integer(4) omp_get_affinity_format integer(4) omp_capture_affinity + + external omp_pause_resource, omp_pause_resource_all + integer(4) omp_pause_resource + integer(4) omp_pause_resource_all diff --git a/libgomp/target.c b/libgomp/target.c index 3713132cf2fd..d9288274243d 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -2503,6 +2503,31 @@ omp_target_disassociate_ptr (const void *ptr, int device_num) return ret; } +int +omp_pause_resource (omp_pause_resource_t kind, int device_num) +{ + (void) kind; + if (device_num == GOMP_DEVICE_HOST_FALLBACK) + return gomp_pause_host (); + if (device_num < 0 || device_num >= gomp_get_num_devices ()) + return -1; + /* Do nothing for target devices for now. */ + return 0; +} + +int +omp_pause_resource_all (omp_pause_resource_t kind) +{ + (void) kind; + if (gomp_pause_host ()) + return -1; + /* Do nothing for target devices for now. */ + return 0; +} + +ialias (omp_pause_resource) +ialias (omp_pause_resource_all) + #ifdef PLUGIN_SUPPORT /* This function tries to load a plugin for DEVICE. Name of plugin is passed diff --git a/libgomp/team.c b/libgomp/team.c index d81674870a38..c73a349b56f9 100644 --- a/libgomp/team.c +++ b/libgomp/team.c @@ -32,7 +32,6 @@ #include #ifdef LIBGOMP_USE_PTHREADS -/* This attribute contains PTHREAD_CREATE_DETACHED. */ pthread_attr_t gomp_thread_attr; /* This key is for the thread destructor. */ @@ -135,6 +134,7 @@ gomp_thread_start (void *xdata) } gomp_sem_destroy (&thr->release); + pthread_detach (pthread_self ()); thr->thread_pool = NULL; thr->task = NULL; return NULL; @@ -235,6 +235,7 @@ gomp_free_pool_helper (void *thread_pool) thr->thread_pool = NULL; thr->task = NULL; #ifdef LIBGOMP_USE_PTHREADS + pthread_detach (pthread_self ()); pthread_exit (NULL); #elif defined(__nvptx__) asm ("exit;"); @@ -726,7 +727,6 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, { size_t stacksize; pthread_attr_init (&thread_attr); - pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED); if (! pthread_attr_getstacksize (&gomp_thread_attr, &stacksize)) pthread_attr_setstacksize (&thread_attr, stacksize); attr = &thread_attr; @@ -1010,6 +1010,76 @@ team_destructor (void) crashes. */ pthread_key_delete (gomp_thread_destructor); } + +/* Similar to gomp_free_pool_helper, but don't detach itself, + gomp_pause_host will pthread_join those threads. */ + +static void +gomp_pause_pool_helper (void *thread_pool) +{ + struct gomp_thread *thr = gomp_thread (); + struct gomp_thread_pool *pool + = (struct gomp_thread_pool *) thread_pool; + gomp_simple_barrier_wait_last (&pool->threads_dock); + gomp_sem_destroy (&thr->release); + thr->thread_pool = NULL; + thr->task = NULL; + pthread_exit (NULL); +} + +/* Free a thread pool and release its threads. Return non-zero on + failure. */ + +int +gomp_pause_host (void) +{ + struct gomp_thread *thr = gomp_thread (); + struct gomp_thread_pool *pool = thr->thread_pool; + if (thr->ts.level) + return -1; + if (pool) + { + if (pool->threads_used > 0) + { + int i; + pthread_t *thrs + = gomp_alloca (sizeof (pthread_t) * pool->threads_used); + for (i = 1; i < pool->threads_used; i++) + { + struct gomp_thread *nthr = pool->threads[i]; + nthr->fn = gomp_pause_pool_helper; + nthr->data = pool; + thrs[i] = gomp_thread_to_pthread_t (nthr); + } + /* This barrier undocks threads docked on pool->threads_dock. */ + gomp_simple_barrier_wait (&pool->threads_dock); + /* And this waits till all threads have called gomp_barrier_wait_last + in gomp_pause_pool_helper. */ + gomp_simple_barrier_wait (&pool->threads_dock); + /* Now it is safe to destroy the barrier and free the pool. */ + gomp_simple_barrier_destroy (&pool->threads_dock); + +#ifdef HAVE_SYNC_BUILTINS + __sync_fetch_and_add (&gomp_managed_threads, + 1L - pool->threads_used); +#else + gomp_mutex_lock (&gomp_managed_threads_lock); + gomp_managed_threads -= pool->threads_used - 1L; + gomp_mutex_unlock (&gomp_managed_threads_lock); +#endif + for (i = 1; i < pool->threads_used; i++) + pthread_join (thrs[i], NULL); + } + if (pool->last_team) + free_team (pool->last_team); +#ifndef __nvptx__ + free (pool->threads); + free (pool); +#endif + thr->thread_pool = NULL; + } + return 0; +} #endif struct gomp_task_icv * diff --git a/libgomp/testsuite/libgomp.c-c++-common/pause-1.c b/libgomp/testsuite/libgomp.c-c++-common/pause-1.c new file mode 100644 index 000000000000..5367a72832ef --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/pause-1.c @@ -0,0 +1,23 @@ +#include +#include + +int a[64]; + +int +main () +{ + int i; + #pragma omp parallel for + for (i = 0; i < 64; i++) + a[i] = i; + omp_pause_resource (omp_pause_soft, omp_get_initial_device ()); + #pragma omp parallel for + for (i = 0; i < 64; i++) + a[i] += i; + omp_pause_resource_all (omp_pause_hard); + #pragma omp parallel for + for (i = 0; i < 64; i++) + if (a[i] != 2 * i) + abort (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/pause-2.c b/libgomp/testsuite/libgomp.c-c++-common/pause-2.c new file mode 100644 index 000000000000..e4781cdc7075 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/pause-2.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_runtime } */ + +#include +#include + +int t = 128; +#pragma omp threadprivate (t) + +int +main () +{ + #pragma omp parallel + t = omp_get_thread_num () + 256; + #pragma omp parallel + if (t != omp_get_thread_num () + 256) + abort (); + omp_pause_resource (omp_pause_soft, omp_get_initial_device ()); + /* This goes beyond what is required by the standard, we actually + check if the threads other than the initial one have been destroyed. */ + #pragma omp parallel + { + if (omp_get_thread_num () != 0 && t != 128) + abort (); + t = omp_get_thread_num () + 384; + } + #pragma omp parallel + if (t != omp_get_thread_num () + 384) + abort (); + omp_pause_resource_all (omp_pause_hard); + #pragma omp parallel + { + if (omp_get_thread_num () != 0 && t != 128) + abort (); + t = omp_get_thread_num () + 512; + } + #pragma omp parallel + if (t != omp_get_thread_num () + 512) + abort (); + return 0; +}