From: Sebastian Huber Date: Thu, 3 Sep 2015 11:29:59 +0000 (+0000) Subject: [gomp] Thread pool management X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=66c59f92387c99ea5724cba69843f7dfb7593740;p=gcc.git [gomp] Thread pool management libgomp/ChangeLog * config/posix/pool.h: New. * config/rtems/pool.h: Likewise. * config/rtems/proc.c: Likewise. * libgomp.h (gomp_thread_destructor): Declare. * team.c: Include configuration provided "pool.h". (gomp_get_thread_pool): Define in configuration. (gomp_team_end): Call configuration defined gomp_release_thread_pool(). From-SVN: r227441 --- diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index c3e94bfa1bc..e64155ca7e4 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,14 @@ +2015-09-03 Sebastian Huber + + * config/posix/pool.h: New. + * config/rtems/pool.h: Likewise. + * config/rtems/proc.c: Likewise. + * libgomp.h (gomp_thread_destructor): Declare. + * team.c: Include configuration provided "pool.h". + (gomp_get_thread_pool): Define in configuration. + (gomp_team_end): Call configuration defined + gomp_release_thread_pool(). + 2015-09-03 Sebastian Huber * config/rtems/bar.c: New. diff --git a/libgomp/config/posix/pool.h b/libgomp/config/posix/pool.h new file mode 100644 index 00000000000..6c4dc156906 --- /dev/null +++ b/libgomp/config/posix/pool.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2005-2015 Free Software Foundation, Inc. + Contributed by Sebastian Huber . + + 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 + . */ + +/* This is the default implementation of the thread pool management + for libgomp. This type is private to the library. */ + +#ifndef GOMP_POOL_H +#define GOMP_POOL_H 1 + +#include "libgomp.h" + +/* Get the thread pool, allocate and initialize it on demand. */ + +static inline struct gomp_thread_pool * +gomp_get_thread_pool (struct gomp_thread *thr, unsigned nthreads) +{ + struct gomp_thread_pool *pool = thr->thread_pool; + if (__builtin_expect (pool == NULL, 0)) + { + pool = gomp_malloc (sizeof (*pool)); + pool->threads = NULL; + pool->threads_size = 0; + pool->threads_used = 0; + pool->last_team = NULL; + pool->threads_busy = nthreads; + thr->thread_pool = pool; + pthread_setspecific (gomp_thread_destructor, thr); + } + return pool; +} + +static inline void +gomp_release_thread_pool (struct gomp_thread_pool *pool) +{ + /* Do nothing in the default implementation. */ +} + +#endif /* GOMP_POOL_H */ diff --git a/libgomp/config/rtems/pool.h b/libgomp/config/rtems/pool.h new file mode 100644 index 00000000000..0ab68d949f2 --- /dev/null +++ b/libgomp/config/rtems/pool.h @@ -0,0 +1,128 @@ +/* Copyright (C) 2015 Free Software Foundation, Inc. + Contributed by Sebastian Huber . + + 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 + . */ + +/* This is the RTEMS implementation of the thread pool management + for libgomp. This type is private to the library. */ + +#ifndef GOMP_POOL_H +#define GOMP_POOL_H 1 + +#include "libgomp.h" +#include +#include + +/* For each scheduler instance there may be a thread pool reservoir + to limit the number of thread pools used by the OpenMP master threads of this + scheduler instance. The reservoirs are configured via the + GOMP_RTEMS_THREAD_POOLS environment variable. */ +struct gomp_thread_pool_reservoir { + gomp_sem_t available; + gomp_mutex_t lock; + size_t index; + struct gomp_thread_pool *pools[]; +}; + +struct gomp_tls_rtems_data { + struct gomp_thread_pool_reservoir *thread_pool_reservoir; +}; + +extern struct gomp_thread_pool_reservoir **gomp_thread_pool_reservoirs; + +extern __thread struct gomp_tls_rtems_data gomp_tls_rtems_data; + +static inline struct gomp_thread_pool_reservoir * +gomp_get_thread_pool_reservoir (void) +{ + struct gomp_thread_pool_reservoir *res = + gomp_tls_rtems_data.thread_pool_reservoir; + + if (res == NULL && gomp_thread_pool_reservoirs != NULL) + { + struct gomp_thread *thr = gomp_thread (); + thr->thread_pool = gomp_malloc_cleared (sizeof (*thr->thread_pool)); + res = gomp_thread_pool_reservoirs[_Sched_Index ()]; + gomp_tls_rtems_data.thread_pool_reservoir = res; + } + + return res; +} + +static inline struct gomp_thread_pool * +gomp_get_own_thread_pool (struct gomp_thread *thr, unsigned nthreads) +{ + struct gomp_thread_pool *pool = thr->thread_pool; + if (__builtin_expect (pool == NULL, 0)) + { + pool = gomp_malloc_cleared (sizeof (*pool)); + pool->threads_busy = nthreads; + thr->thread_pool = pool; + } + return pool; +} + +static inline struct gomp_thread_pool * +gomp_get_thread_pool (struct gomp_thread *thr, unsigned nthreads) +{ + struct gomp_thread_pool *pool; + + if (__builtin_expect (thr->thread_pool == NULL, 0)) + pthread_setspecific (gomp_thread_destructor, thr); + + if (nthreads != 1) + { + struct gomp_thread_pool_reservoir *res = + gomp_get_thread_pool_reservoir (); + if (res != NULL) + { + gomp_sem_wait (&res->available); + gomp_mutex_lock (&res->lock); + pool = res->pools[--res->index]; + gomp_mutex_unlock (&res->lock); + pool->threads_busy = nthreads; + thr->thread_pool = pool; + } + else + pool = gomp_get_own_thread_pool (thr, nthreads); + } + else + pool = NULL; + return pool; +} + +static inline void +gomp_release_thread_pool (struct gomp_thread_pool *pool) +{ + struct gomp_thread_pool_reservoir *res = + gomp_tls_rtems_data.thread_pool_reservoir; + if (res != NULL) + { + gomp_mutex_lock (&res->lock); + res->pools[res->index++] = pool; + gomp_mutex_unlock (&res->lock); + gomp_sem_post (&res->available); + } +} + +#endif /* GOMP_POOL_H */ diff --git a/libgomp/config/rtems/proc.c b/libgomp/config/rtems/proc.c new file mode 100644 index 00000000000..e879a9d41bb --- /dev/null +++ b/libgomp/config/rtems/proc.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2015 Free Software Foundation, Inc. + Contributed by Sebastian Huber . + + 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 + . */ + +/* This file contains RTEMS specific routines related to counting + online processors and dynamic load balancing. */ + +#include "libgomp.h" +#include "pool.h" +#include +#include +#include +#include + +struct gomp_thread_pool_reservoir **gomp_thread_pool_reservoirs; + +__thread struct gomp_tls_rtems_data gomp_tls_rtems_data; + +static void +allocate_thread_pool_reservoirs (void) +{ + struct gomp_thread_pool_reservoir **reservoirs; + size_t size = _Sched_Count () * sizeof (*reservoirs); + reservoirs = gomp_malloc (size); + gomp_thread_pool_reservoirs = reservoirs; + memset (reservoirs, 0, size); +} + +static void +allocate_thread_pool_reservoir (unsigned long count, unsigned long scheduler) +{ + struct gomp_thread_pool_reservoir *res; + struct gomp_thread_pool *pools; + unsigned long i; + size_t size; + + res = gomp_thread_pool_reservoirs[scheduler]; + if (res != NULL) + gomp_fatal ("Multiple thread pool reservoir initialization"); + size = sizeof (*res) + count * (sizeof(pools) + sizeof(*pools)); + pools = gomp_malloc (size); + memset (pools, 0, size); + res = (struct gomp_thread_pool_reservoir *) (pools + count); + res->index = count; + gomp_sem_init (&res->available, count); + gomp_mutex_init (&res->lock); + for (i = 0; i < count; ++i) + res->pools[i] = &pools[i]; + gomp_thread_pool_reservoirs[scheduler] = res; +} + +static char * +parse_thread_pools (char *env, unsigned long *count, unsigned long *scheduler) +{ + size_t len; + int i; + + if (*env == ':') + ++env; + + errno = 0; + *count = strtoul (env, &env, 10); + if (errno != 0) + gomp_fatal ("Invalid thread pool count"); + + if (*env != '@') + gomp_fatal ("Invalid thread pool scheduler prefix"); + ++env; + + len = 0; + while (env[len] != '\0' && env[len] != ':') + ++len; + i = _Sched_Name_to_index (env, len); + if (i < 0) + gomp_fatal ("Invalid thread pool scheduler"); + *scheduler = i; + env += len; + + return env; +} + +static void +init_thread_pool_reservoirs (void) +{ + char *env = getenv ("GOMP_RTEMS_THREAD_POOLS"); + if (env != NULL) + { + allocate_thread_pool_reservoirs (); + while (*env != '\0') + { + unsigned long count; + unsigned long scheduler; + env = parse_thread_pools (env, &count, &scheduler); + allocate_thread_pool_reservoir (count, scheduler); + } + } +} + +void +gomp_init_num_threads (void) +{ + gomp_global_icv.nthreads_var = omp_get_num_procs(); + init_thread_pool_reservoirs (); +} + +unsigned +gomp_dynamic_max_threads (void) +{ + unsigned n_onln = (unsigned) omp_get_num_procs(); + unsigned nthreads_var = gomp_icv (false)->nthreads_var; + + if (n_onln > nthreads_var) + return nthreads_var; + else + return n_onln; +} + +int +omp_get_num_procs (void) +{ + return sysconf (_SC_NPROCESSORS_ONLN); +} + +ialias (omp_get_num_procs) diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index 62454b8527a..2ea1c5d857b 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -513,6 +513,8 @@ static inline struct gomp_task_icv *gomp_icv (bool write) /* The attributes to be used during thread creation. */ extern pthread_attr_t gomp_thread_attr; +extern pthread_key_t gomp_thread_destructor; + /* Function prototypes. */ /* affinity.c */ diff --git a/libgomp/team.c b/libgomp/team.c index e1c4d60270e..274f3ed8a66 100644 --- a/libgomp/team.c +++ b/libgomp/team.c @@ -27,6 +27,7 @@ creation and termination. */ #include "libgomp.h" +#include "pool.h" #include #include @@ -134,26 +135,6 @@ gomp_thread_start (void *xdata) return NULL; } -/* Get the thread pool, allocate and initialize it on demand. */ - -static inline struct gomp_thread_pool * -gomp_get_thread_pool (struct gomp_thread *thr, unsigned nthreads) -{ - struct gomp_thread_pool *pool = thr->thread_pool; - if (__builtin_expect (pool == NULL, 0)) - { - pool = gomp_malloc (sizeof (*pool)); - pool->threads = NULL; - pool->threads_size = 0; - pool->threads_used = 0; - pool->last_team = NULL; - pool->threads_busy = nthreads; - thr->thread_pool = pool; - pthread_setspecific (gomp_thread_destructor, thr); - } - return pool; -} - static inline struct gomp_team * get_last_team (unsigned nthreads) { @@ -930,6 +911,7 @@ gomp_team_end (void) if (pool->last_team) free_team (pool->last_team); pool->last_team = team; + gomp_release_thread_pool (pool); } }