diff options
Diffstat (limited to 'libgomp/config/posix')
-rw-r--r-- | libgomp/config/posix/bar.c | 76 | ||||
-rw-r--r-- | libgomp/config/posix/bar.h | 63 | ||||
-rw-r--r-- | libgomp/config/posix/lock.c | 207 | ||||
-rw-r--r-- | libgomp/config/posix/omp-lock.h | 18 | ||||
-rw-r--r-- | libgomp/config/posix/proc.c | 13 | ||||
-rw-r--r-- | libgomp/config/posix/ptrlock.c | 1 | ||||
-rw-r--r-- | libgomp/config/posix/ptrlock.h | 69 |
7 files changed, 420 insertions, 27 deletions
diff --git a/libgomp/config/posix/bar.c b/libgomp/config/posix/bar.c index 79721610ca7..ff19e9353a3 100644 --- a/libgomp/config/posix/bar.c +++ b/libgomp/config/posix/bar.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2008 Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com>. This file is part of the GNU OpenMP Library (libgomp). @@ -44,6 +44,7 @@ gomp_barrier_init (gomp_barrier_t *bar, unsigned count) gomp_sem_init (&bar->sem2, 0); bar->total = count; bar->arrived = 0; + bar->generation = 0; } void @@ -70,11 +71,11 @@ gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count) } void -gomp_barrier_wait_end (gomp_barrier_t *bar, bool last) +gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state) { unsigned int n; - if (last) + if (state & 1) { n = --bar->arrived; if (n > 0) @@ -109,3 +110,72 @@ gomp_barrier_wait (gomp_barrier_t *barrier) { gomp_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier)); } + +void +gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state) +{ + unsigned int n; + + if (state & 1) + { + n = --bar->arrived; + struct gomp_thread *thr = gomp_thread (); + struct gomp_team *team = thr->ts.team; + + if (team->task_count) + { + gomp_barrier_handle_tasks (state); + if (n > 0) + gomp_sem_wait (&bar->sem2); + gomp_mutex_unlock (&bar->mutex1); + return; + } + + bar->generation = state + 3; + if (n > 0) + { + do + gomp_sem_post (&bar->sem1); + while (--n != 0); + gomp_sem_wait (&bar->sem2); + } + gomp_mutex_unlock (&bar->mutex1); + } + else + { + gomp_mutex_unlock (&bar->mutex1); + do + { + gomp_sem_wait (&bar->sem1); + if (bar->generation & 1) + gomp_barrier_handle_tasks (state); + } + while (bar->generation != state + 4); + +#ifdef HAVE_SYNC_BUILTINS + n = __sync_add_and_fetch (&bar->arrived, -1); +#else + gomp_mutex_lock (&bar->mutex2); + n = --bar->arrived; + gomp_mutex_unlock (&bar->mutex2); +#endif + + if (n == 0) + gomp_sem_post (&bar->sem2); + } +} + +void +gomp_team_barrier_wait (gomp_barrier_t *barrier) +{ + gomp_team_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier)); +} + +void +gomp_team_barrier_wake (gomp_barrier_t *bar, int count) +{ + if (count == 0) + count = bar->total - 1; + while (count-- > 0) + gomp_sem_post (&bar->sem1); +} diff --git a/libgomp/config/posix/bar.h b/libgomp/config/posix/bar.h index 5275efa96a7..e4d2e680af2 100644 --- a/libgomp/config/posix/bar.h +++ b/libgomp/config/posix/bar.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2008 Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com>. This file is part of the GNU OpenMP Library (libgomp). @@ -45,19 +45,74 @@ typedef struct gomp_sem_t sem2; unsigned total; unsigned arrived; + unsigned generation; } gomp_barrier_t; +typedef unsigned int gomp_barrier_state_t; extern void gomp_barrier_init (gomp_barrier_t *, unsigned); extern void gomp_barrier_reinit (gomp_barrier_t *, unsigned); extern void gomp_barrier_destroy (gomp_barrier_t *); extern void gomp_barrier_wait (gomp_barrier_t *); -extern void gomp_barrier_wait_end (gomp_barrier_t *, bool); +extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t); +extern void gomp_team_barrier_wait (gomp_barrier_t *); +extern void gomp_team_barrier_wait_end (gomp_barrier_t *, + gomp_barrier_state_t); +extern void gomp_team_barrier_wake (gomp_barrier_t *, int); -static inline bool gomp_barrier_wait_start (gomp_barrier_t *bar) +static inline gomp_barrier_state_t +gomp_barrier_wait_start (gomp_barrier_t *bar) { + unsigned int ret; gomp_mutex_lock (&bar->mutex1); - return ++bar->arrived == bar->total; + ret = bar->generation & ~3; + ret += ++bar->arrived == bar->total; + return ret; +} + +static inline bool +gomp_barrier_last_thread (gomp_barrier_state_t state) +{ + return state & 1; +} + +static inline void +gomp_barrier_wait_last (gomp_barrier_t *bar) +{ + gomp_barrier_wait (bar); +} + +/* All the inlines below must be called with team->task_lock + held. */ + +static inline void +gomp_team_barrier_set_task_pending (gomp_barrier_t *bar) +{ + bar->generation |= 1; +} + +static inline void +gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar) +{ + bar->generation &= ~1; +} + +static inline void +gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar) +{ + bar->generation |= 2; +} + +static inline bool +gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar) +{ + return (bar->generation & 2) != 0; +} + +static inline void +gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state) +{ + bar->generation = (state & ~3) + 4; } #endif /* GOMP_BARRIER_H */ diff --git a/libgomp/config/posix/lock.c b/libgomp/config/posix/lock.c index 59459bb86ce..c2868398c66 100644 --- a/libgomp/config/posix/lock.c +++ b/libgomp/config/posix/lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2008 Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com>. This file is part of the GNU OpenMP Library (libgomp). @@ -42,39 +42,209 @@ #include "libgomp.h" +#ifdef HAVE_BROKEN_POSIX_SEMAPHORES +void +gomp_init_lock_30 (omp_lock_t *lock) +{ + pthread_mutex_init (lock, NULL); +} + +void +gomp_destroy_lock_30 (omp_lock_t *lock) +{ + pthread_mutex_destroy (lock); +} + +void +gomp_set_lock_30 (omp_lock_t *lock) +{ + pthread_mutex_lock (lock); +} + +void +gomp_unset_lock_30 (omp_lock_t *lock) +{ + pthread_mutex_unlock (lock); +} + +int +gomp_test_lock_30 (omp_lock_t *lock) +{ + return pthread_mutex_trylock (lock) == 0; +} + +void +gomp_init_nest_lock_30 (omp_nest_lock_t *lock) +{ + pthread_mutex_init (&lock->lock, NULL); + lock->count = 0; + lock->owner = NULL; +} + +void +gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock) +{ + pthread_mutex_destroy (&lock->lock); +} + +void +gomp_set_nest_lock_30 (omp_nest_lock_t *lock) +{ + void *me = gomp_icv (true); + + if (lock->owner != me) + { + pthread_mutex_lock (&lock->lock); + lock->owner = me; + } + lock->count++; +} + +void +gomp_unset_nest_lock_30 (omp_nest_lock_t *lock) +{ + if (--lock->count == 0) + { + lock->owner = NULL; + pthread_mutex_unlock (&lock->lock); + } +} + +int +gomp_test_nest_lock_30 (omp_nest_lock_t *lock) +{ + void *me = gomp_icv (true); + + if (lock->owner != me) + { + if (pthread_mutex_trylock (&lock->lock) != 0) + return 0; + lock->owner = me; + } + + return ++lock->count; +} + +#else void -omp_init_lock (omp_lock_t *lock) +gomp_init_lock_30 (omp_lock_t *lock) +{ + sem_init (lock, 0, 1); +} + +void +gomp_destroy_lock_30 (omp_lock_t *lock) +{ + sem_destroy (lock); +} + +void +gomp_set_lock_30 (omp_lock_t *lock) +{ + while (sem_wait (lock) != 0) + ; +} + +void +gomp_unset_lock_30 (omp_lock_t *lock) +{ + sem_post (lock); +} + +int +gomp_test_lock_30 (omp_lock_t *lock) +{ + return sem_trywait (lock) == 0; +} + +void +gomp_init_nest_lock_30 (omp_nest_lock_t *lock) +{ + sem_init (&lock->lock, 0, 1); + lock->count = 0; + lock->owner = NULL; +} + +void +gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock) +{ + sem_destroy (&lock->lock); +} + +void +gomp_set_nest_lock_30 (omp_nest_lock_t *lock) +{ + void *me = gomp_icv (true); + + if (lock->owner != me) + { + while (sem_wait (&lock->lock) != 0) + ; + lock->owner = me; + } + lock->count++; +} + +void +gomp_unset_nest_lock_30 (omp_nest_lock_t *lock) +{ + if (--lock->count == 0) + { + lock->owner = NULL; + sem_post (&lock->lock); + } +} + +int +gomp_test_nest_lock_30 (omp_nest_lock_t *lock) +{ + void *me = gomp_icv (true); + + if (lock->owner != me) + { + if (sem_trywait (&lock->lock) != 0) + return 0; + lock->owner = me; + } + + return ++lock->count; +} +#endif + +#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING +void +gomp_init_lock_25 (omp_lock_25_t *lock) { pthread_mutex_init (lock, NULL); } void -omp_destroy_lock (omp_lock_t *lock) +gomp_destroy_lock_25 (omp_lock_25_t *lock) { pthread_mutex_destroy (lock); } void -omp_set_lock (omp_lock_t *lock) +gomp_set_lock_25 (omp_lock_25_t *lock) { pthread_mutex_lock (lock); } void -omp_unset_lock (omp_lock_t *lock) +gomp_unset_lock_25 (omp_lock_25_t *lock) { pthread_mutex_unlock (lock); } int -omp_test_lock (omp_lock_t *lock) +gomp_test_lock_25 (omp_lock_25_t *lock) { return pthread_mutex_trylock (lock) == 0; } void -omp_init_nest_lock (omp_nest_lock_t *lock) +gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock) { pthread_mutexattr_t attr; @@ -86,33 +256,46 @@ omp_init_nest_lock (omp_nest_lock_t *lock) } void -omp_destroy_nest_lock (omp_nest_lock_t *lock) +gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock) { pthread_mutex_destroy (&lock->lock); } void -omp_set_nest_lock (omp_nest_lock_t *lock) +gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock) { pthread_mutex_lock (&lock->lock); lock->count++; } void -omp_unset_nest_lock (omp_nest_lock_t *lock) +gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock) { lock->count--; pthread_mutex_unlock (&lock->lock); } int -omp_test_nest_lock (omp_nest_lock_t *lock) +gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock) { if (pthread_mutex_trylock (&lock->lock) == 0) return ++lock->count; return 0; } +omp_lock_symver (omp_init_lock) +omp_lock_symver (omp_destroy_lock) +omp_lock_symver (omp_set_lock) +omp_lock_symver (omp_unset_lock) +omp_lock_symver (omp_test_lock) +omp_lock_symver (omp_init_nest_lock) +omp_lock_symver (omp_destroy_nest_lock) +omp_lock_symver (omp_set_nest_lock) +omp_lock_symver (omp_unset_nest_lock) +omp_lock_symver (omp_test_nest_lock) + +#else + ialias (omp_init_lock) ialias (omp_init_nest_lock) ialias (omp_destroy_lock) @@ -123,3 +306,5 @@ ialias (omp_unset_lock) ialias (omp_unset_nest_lock) ialias (omp_test_lock) ialias (omp_test_nest_lock) + +#endif diff --git a/libgomp/config/posix/omp-lock.h b/libgomp/config/posix/omp-lock.h index ed70618d87d..e51dc271f8a 100644 --- a/libgomp/config/posix/omp-lock.h +++ b/libgomp/config/posix/omp-lock.h @@ -2,10 +2,22 @@ alignment of the public OpenMP locks, so that we can export data structures without polluting the namespace. - In this default POSIX implementation, we map the two locks to the - same PTHREADS primitive. */ + In this default POSIX implementation, we used to map the two locks to the + same PTHREADS primitive, but for OpenMP 3.0 sem_t needs to be used + instead, as pthread_mutex_unlock should not be called by different + thread than the one that called pthread_mutex_lock. */ #include <pthread.h> +#include <semaphore.h> +typedef pthread_mutex_t omp_lock_25_t; +typedef struct { pthread_mutex_t lock; int count; } omp_nest_lock_25_t; +#ifdef HAVE_BROKEN_POSIX_SEMAPHORES +/* If we don't have working semaphores, we'll make all explicit tasks + tied to the creating thread. */ typedef pthread_mutex_t omp_lock_t; -typedef struct { pthread_mutex_t lock; int count; } omp_nest_lock_t; +typedef struct { pthread_mutex_t lock; int count; void *owner; } omp_nest_lock_t; +#else +typedef sem_t omp_lock_t; +typedef struct { sem_t lock; int count; void *owner; } omp_nest_lock_t; +#endif diff --git a/libgomp/config/posix/proc.c b/libgomp/config/posix/proc.c index 3ee84f5c9d6..0c1096fb6b1 100644 --- a/libgomp/config/posix/proc.c +++ b/libgomp/config/posix/proc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com>. This file is part of the GNU OpenMP Library (libgomp). @@ -48,7 +48,7 @@ void gomp_init_num_threads (void) { #ifdef _SC_NPROCESSORS_ONLN - gomp_nthreads_var = sysconf (_SC_NPROCESSORS_ONLN); + gomp_global_icv.nthreads_var = sysconf (_SC_NPROCESSORS_ONLN); #endif } @@ -63,13 +63,14 @@ unsigned gomp_dynamic_max_threads (void) { unsigned n_onln, loadavg; + unsigned nthreads_var = gomp_icv (false)->nthreads_var; #ifdef _SC_NPROCESSORS_ONLN n_onln = sysconf (_SC_NPROCESSORS_ONLN); - if (n_onln > gomp_nthreads_var) - n_onln = gomp_nthreads_var; + if (n_onln > nthreads_var) + n_onln = nthreads_var; #else - n_onln = gomp_nthreads_var; + n_onln = nthreads_var; #endif loadavg = 0; @@ -96,7 +97,7 @@ omp_get_num_procs (void) #ifdef _SC_NPROCESSORS_ONLN return sysconf (_SC_NPROCESSORS_ONLN); #else - return gomp_nthreads_var; + return gomp_icv (false)->nthreads_var; #endif } diff --git a/libgomp/config/posix/ptrlock.c b/libgomp/config/posix/ptrlock.c new file mode 100644 index 00000000000..39bb64da0f9 --- /dev/null +++ b/libgomp/config/posix/ptrlock.c @@ -0,0 +1 @@ +/* Everything is in the header. */ diff --git a/libgomp/config/posix/ptrlock.h b/libgomp/config/posix/ptrlock.h new file mode 100644 index 00000000000..1271ebb227b --- /dev/null +++ b/libgomp/config/posix/ptrlock.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + This file is part of the GNU OpenMP Library (libgomp). + + Libgomp is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for + more details. + + You should have received a copy of the GNU Lesser General Public License + along with libgomp; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* As a special exception, if you link this library with other files, some + of which are compiled with GCC, to produce an executable, this library + does not by itself cause the resulting executable to be covered by the + GNU General Public License. This exception does not however invalidate + any other reasons why the executable file might be covered by the GNU + General Public License. */ + +/* This is a Linux specific implementation of a mutex synchronization + mechanism for libgomp. This type is private to the library. This + implementation uses atomic instructions and the futex syscall. */ + +#ifndef GOMP_PTRLOCK_H +#define GOMP_PTRLOCK_H 1 + +typedef struct { void *ptr; gomp_mutex_t lock; } gomp_ptrlock_t; + +static inline void gomp_ptrlock_init (gomp_ptrlock_t *ptrlock, void *ptr) +{ + ptrlock->ptr = ptr; + gomp_mutex_init (&ptrlock->lock); +} + +static inline void *gomp_ptrlock_get (gomp_ptrlock_t *ptrlock) +{ + if (ptrlock->ptr != NULL) + return ptrlock->ptr; + + gomp_mutex_lock (&ptrlock->lock); + if (ptrlock->ptr != NULL) + { + gomp_mutex_unlock (&ptrlock->lock); + return ptrlock->ptr; + } + + return NULL; +} + +static inline void gomp_ptrlock_set (gomp_ptrlock_t *ptrlock, void *ptr) +{ + ptrlock->ptr = ptr; + gomp_mutex_unlock (&ptrlock->lock); +} + +static inline void gomp_ptrlock_destroy (gomp_ptrlock_t *ptrlock) +{ + gomp_mutex_destroy (&ptrlock->lock); +} + +#endif /* GOMP_PTRLOCK_H */ |