summaryrefslogtreecommitdiff
path: root/libgomp/config/posix
diff options
context:
space:
mode:
Diffstat (limited to 'libgomp/config/posix')
-rw-r--r--libgomp/config/posix/bar.c76
-rw-r--r--libgomp/config/posix/bar.h63
-rw-r--r--libgomp/config/posix/lock.c207
-rw-r--r--libgomp/config/posix/omp-lock.h18
-rw-r--r--libgomp/config/posix/proc.c13
-rw-r--r--libgomp/config/posix/ptrlock.c1
-rw-r--r--libgomp/config/posix/ptrlock.h69
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 */