[gomp3] omp*_lock changes

Jakub Jelinek jakub@redhat.com
Fri Mar 7 22:40:00 GMT 2008


Hi!

OpenMP 3.0 changed behavior of omp_lock_t/omp_nest_lock_t and
the functions using those locks, previously locks were owned by threads,
now they are owned by tasks.  In some cases valid OpenMP 2.5 code is
invalid OpenMP 3.0, e.g. see lock-1.c testcase below.
The Linux futex-based omp_lock_t is the only one that doesn't need changes,
as it doesn't care about owner.  But already Linux futex-based
omp_nest_lock_t needs changes, as the owner really needs to be some
task specific pointer and so size of omp_nest_lock_t has to change.
Even bigger changes are needed in posix and posix95 locks - as
untied explicit tasks can migrate from one thread to another,
we can't use pthread_mutex_lock/pthread_mutex_unlock, as it is undefined
behavior if you pthread_mutex_unlock in a different thread than the thread
that called pthread_mutex_lock.  So, I'm using semaphores if they aren't
broken, if semaphores are broken (darwin?), then we'll just need to prevent
untied task migration from one thread to another one.
If libgomp.so.1 is symbol versioned, for compatibility the old routines
are provided, as omp*_lock_t types are changing.

I've tested this on Linux with default configuration, and additionally
tested with further 4 configurations - using config/posix/ rather than
config/linux and using config/posix95/ config/posix/ and not config/linux,
each time both with broken and non-broken semaphores configuration.  All
these built and passed make check.

I'll commit on Monday unless I hear objections.

2008-02-07  Jakub Jelinek  <jakub@redhat.com>

	* config/linux/lock.c: Rewrite to make locks task owned,
	for backwards compatibility provide the old entrypoints
	if symbol versioning.
	* config/linux/omp-lock.h (omp_lock_25_t, omp_nest_lock_25_t): New
	types.
	(omp_nest_lock_t): Change owner into void *, add lock field.
	* config/posix95/lock.c: Rewrite to make locks task owned,
	for backwards compatibility provide the old entrypoints
	if symbol versioning.
	* config/posix95/omp-lock.h: Include semaphore.h.
	(omp_lock_25_t, omp_nest_lock_25_t): New types.
	(omp_lock_t): Use sem_t instead of mutex if semaphores
	aren't broken.
	(omp_nest_lock_t): Likewise.  Change owner to void *.
	* config/posix/lock.c: Rewrite to make locks task owned,
	for backwards compatibility provide the old entrypoints
	if symbol versioning.
	* config/posix/omp-lock.h: Include semaphore.h.
	(omp_lock_25_t, omp_nest_lock_25_t): New types.
	(omp_lock_t): Use sem_t instead of mutex if semaphores
	aren't broken.
	(omp_nest_lock_t): Likewise.  Add owner field.
	* libgomp_f.h.in (omp_lock_25_arg_t, omp_nest_lock_25_arg_t): New
	types.
	(omp_lock_25_arg, omp_nest_lock_25_arg): New macros.
	(omp_check_defines): Check even the compat defines.
	* libgomp.h (LIBGOMP_GNU_SYMBOL_VERSIONING): Undef if no visibility
	or no alias support, or if not PIC.
	(gomp_init_lock_30, gomp_destroy_lock_30, gomp_set_lock_30,
	gomp_unset_lock_30, gomp_test_lock_30, gomp_init_nest_lock_30,
	gomp_destroy_nest_lock_30, gomp_set_nest_lock_30,
	gomp_unset_nest_lock_30, gomp_test_nest_lock_30, gomp_init_lock_25,
	gomp_destroy_lock_25, gomp_set_lock_25, gomp_unset_lock_25,
	gomp_test_lock_25, gomp_init_nest_lock_25, gomp_destroy_nest_lock_25,
	gomp_set_nest_lock_25, gomp_unset_nest_lock_25,
	gomp_test_nest_lock_25): New prototypes.
	(omp_lock_symver, strong_alias): Define.
	* fortran.c: Rewrite lock wrappers, if symbol versioning provide
	both wrappers for compatibility and new locks.
	* libgomp.map: Export lock routines also @@OMP_2.0.
	* configure.ac (LIBGOMP_GNU_SYMBOL_VERSIONING): New AC_DEFINE.
	Substitute also OMP_*LOCK_25*.
	* configure: Regenerated.
	* config.h.in: Regenerated.
	* testsuite/libgomp.fortran/lock-1.f90: New test.
	* testsuite/libgomp.fortran/lock-2.f90: New test.
	* testsuite/libgomp.c/lock-1.c: New test.
	* testsuite/libgomp.c/lock-2.c: New test.

--- libgomp_f.h.in	(revision 132481)
+++ libgomp_f.h.in	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -53,6 +53,26 @@ typedef union { omp_nest_lock_t *lock; u
 # define omp_nest_lock_arg(arg) ((arg)->lock)
 # endif
 
+#if (@OMP_LOCK_25_SIZE@ == @OMP_LOCK_25_KIND@) \
+    && (@OMP_LOCK_25_ALIGN@ <= @OMP_LOCK_25_SIZE@)
+# define OMP_LOCK_25_DIRECT
+typedef omp_lock_25_t *omp_lock_25_arg_t;
+# define omp_lock_25_arg(arg) (arg)
+#else
+typedef union { omp_lock_25_t *lock; uint64_t u; } *omp_lock_25_arg_t;
+# define omp_lock_25_arg(arg) ((arg)->lock)
+# endif
+
+#if (@OMP_NEST_LOCK_25_SIZE@ == @OMP_NEST_LOCK_25_KIND@) \
+    && (@OMP_NEST_LOCK_25_ALIGN@ <= @OMP_NEST_LOCK_25_SIZE@)
+# define OMP_NEST_LOCK_25_DIRECT
+typedef omp_nest_lock_25_t *omp_nest_lock_25_arg_t;
+# define omp_nest_lock_25_arg(arg) (arg)
+#else
+typedef union { omp_nest_lock_25_t *lock; uint64_t u; } *omp_nest_lock_25_arg_t;
+# define omp_nest_lock_25_arg(arg) ((arg)->lock)
+# endif
+
 static inline void
 omp_check_defines (void)
 {
@@ -63,6 +83,14 @@ omp_check_defines (void)
 	     || @OMP_LOCK_KIND@ != sizeof (*(omp_lock_arg_t) 0)
 	     || @OMP_NEST_LOCK_KIND@ != sizeof (*(omp_nest_lock_arg_t) 0))
 	    ? -1 : 1] __attribute__ ((__unused__));
+  char test2[(@OMP_LOCK_25_SIZE@ != sizeof (omp_lock_25_t)
+	     || @OMP_LOCK_25_ALIGN@ != __alignof (omp_lock_25_t)
+	     || @OMP_NEST_LOCK_25_SIZE@ != sizeof (omp_nest_lock_25_t)
+	     || @OMP_NEST_LOCK_25_ALIGN@ != __alignof (omp_nest_lock_25_t)
+	     || @OMP_LOCK_25_KIND@ != sizeof (*(omp_lock_25_arg_t) 0)
+	     || @OMP_NEST_LOCK_25_KIND@
+		!= sizeof (*(omp_nest_lock_25_arg_t) 0))
+	    ? -1 : 1] __attribute__ ((__unused__));
 }
 
 #endif /* LIBGOMP_F_H */
--- fortran.c	(revision 132481)
+++ fortran.c	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -33,11 +33,12 @@
 
 #ifdef HAVE_ATTRIBUTE_ALIAS
 /* Use internal aliases if possible.  */
-#define ULP	STR1(__USER_LABEL_PREFIX__)
-#define STR1(x)	STR2(x)
-#define STR2(x)	#x
+# define ULP		STR1(__USER_LABEL_PREFIX__)
+# define STR1(x)	STR2(x)
+# define STR2(x)	#x
 # define ialias_redirect(fn) \
   extern __typeof (fn) fn __asm__ (ULP "gomp_ialias_" #fn) attribute_hidden;
+# ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
 ialias_redirect (omp_init_lock)
 ialias_redirect (omp_init_nest_lock)
 ialias_redirect (omp_destroy_lock)
@@ -48,6 +49,7 @@ ialias_redirect (omp_unset_lock)
 ialias_redirect (omp_unset_nest_lock)
 ialias_redirect (omp_test_lock)
 ialias_redirect (omp_test_nest_lock)
+# endif
 ialias_redirect (omp_set_dynamic)
 ialias_redirect (omp_set_nested)
 ialias_redirect (omp_set_num_threads)
@@ -69,30 +71,43 @@ ialias_redirect (omp_get_level)
 ialias_redirect (omp_get_ancestor_thread_num)
 ialias_redirect (omp_get_team_size)
 ialias_redirect (omp_get_active_level)
-#endif        
+#endif
+
+#ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
+# define gomp_init_lock__30 omp_init_lock_
+# define gomp_destroy_lock__30 omp_destroy_lock_
+# define gomp_set_lock__30 omp_set_lock_
+# define gomp_unset_lock__30 omp_unset_lock_
+# define gomp_test_lock__30 omp_test_lock_
+# define gomp_init_nest_lock__30 omp_init_nest_lock_
+# define gomp_destroy_nest_lock__30 omp_destroy_nest_lock_
+# define gomp_set_nest_lock__30 omp_set_nest_lock_
+# define gomp_unset_nest_lock__30 omp_unset_nest_lock_
+# define gomp_test_nest_lock__30 omp_test_nest_lock_
+#endif
 
 void
-omp_init_lock_ (omp_lock_arg_t lock)
+gomp_init_lock__30 (omp_lock_arg_t lock)
 {
 #ifndef OMP_LOCK_DIRECT
   omp_lock_arg (lock) = malloc (sizeof (omp_lock_t));
 #endif
-  omp_init_lock (omp_lock_arg (lock));
+  gomp_init_lock_30 (omp_lock_arg (lock));
 }
 
 void
-omp_init_nest_lock_ (omp_nest_lock_arg_t lock)
+gomp_init_nest_lock__30 (omp_nest_lock_arg_t lock)
 {
 #ifndef OMP_NEST_LOCK_DIRECT
   omp_nest_lock_arg (lock) = malloc (sizeof (omp_nest_lock_t));
 #endif
-  omp_init_nest_lock (omp_nest_lock_arg (lock));
+  gomp_init_nest_lock_30 (omp_nest_lock_arg (lock));
 }
 
 void
-omp_destroy_lock_ (omp_lock_arg_t lock)
+gomp_destroy_lock__30 (omp_lock_arg_t lock)
 {
-  omp_destroy_lock (omp_lock_arg (lock));
+  gomp_destroy_lock_30 (omp_lock_arg (lock));
 #ifndef OMP_LOCK_DIRECT
   free (omp_lock_arg (lock));
   omp_lock_arg (lock) = NULL;
@@ -100,9 +115,9 @@ omp_destroy_lock_ (omp_lock_arg_t lock)
 }
 
 void
-omp_destroy_nest_lock_ (omp_nest_lock_arg_t lock)
+gomp_destroy_nest_lock__30 (omp_nest_lock_arg_t lock)
 {
-  omp_destroy_nest_lock (omp_nest_lock_arg (lock));
+  gomp_destroy_nest_lock_30 (omp_nest_lock_arg (lock));
 #ifndef OMP_NEST_LOCK_DIRECT
   free (omp_nest_lock_arg (lock));
   omp_nest_lock_arg (lock) = NULL;
@@ -110,30 +125,129 @@ omp_destroy_nest_lock_ (omp_nest_lock_ar
 }
 
 void
-omp_set_lock_ (omp_lock_arg_t lock)
+gomp_set_lock__30 (omp_lock_arg_t lock)
 {
-  omp_set_lock (omp_lock_arg (lock));
+  gomp_set_lock_30 (omp_lock_arg (lock));
 }
 
 void
-omp_set_nest_lock_ (omp_nest_lock_arg_t lock)
+gomp_set_nest_lock__30 (omp_nest_lock_arg_t lock)
 {
-  omp_set_nest_lock (omp_nest_lock_arg (lock));
+  gomp_set_nest_lock_30 (omp_nest_lock_arg (lock));
 }
 
 void
-omp_unset_lock_ (omp_lock_arg_t lock)
+gomp_unset_lock__30 (omp_lock_arg_t lock)
 {
-  omp_unset_lock (omp_lock_arg (lock));
+  gomp_unset_lock_30 (omp_lock_arg (lock));
 }
 
 void
-omp_unset_nest_lock_ (omp_nest_lock_arg_t lock)
+gomp_unset_nest_lock__30 (omp_nest_lock_arg_t lock)
 {
-  omp_unset_nest_lock (omp_nest_lock_arg (lock));
+  gomp_unset_nest_lock_30 (omp_nest_lock_arg (lock));
+}
+
+int32_t
+gomp_test_lock__30 (omp_lock_arg_t lock)
+{
+  return gomp_test_lock_30 (omp_lock_arg (lock));
+}
+
+int32_t
+gomp_test_nest_lock__30 (omp_nest_lock_arg_t lock)
+{
+  return gomp_test_nest_lock_30 (omp_nest_lock_arg (lock));
+}
+
+#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
+void
+gomp_init_lock__25 (omp_lock_25_arg_t lock)
+{
+#ifndef OMP_LOCK_25_DIRECT
+  omp_lock_25_arg (lock) = malloc (sizeof (omp_lock_25_t));
+#endif
+  gomp_init_lock_25 (omp_lock_25_arg (lock));
 }
 
 void
+gomp_init_nest_lock__25 (omp_nest_lock_25_arg_t lock)
+{
+#ifndef OMP_NEST_LOCK_25_DIRECT
+  omp_nest_lock_25_arg (lock) = malloc (sizeof (omp_nest_lock_25_t));
+#endif
+  gomp_init_nest_lock_25 (omp_nest_lock_25_arg (lock));
+}
+
+void
+gomp_destroy_lock__25 (omp_lock_25_arg_t lock)
+{
+  gomp_destroy_lock_25 (omp_lock_25_arg (lock));
+#ifndef OMP_LOCK_25_DIRECT
+  free (omp_lock_25_arg (lock));
+  omp_lock_25_arg (lock) = NULL;
+#endif
+}
+
+void
+gomp_destroy_nest_lock__25 (omp_nest_lock_25_arg_t lock)
+{
+  gomp_destroy_nest_lock_25 (omp_nest_lock_25_arg (lock));
+#ifndef OMP_NEST_LOCK_25_DIRECT
+  free (omp_nest_lock_25_arg (lock));
+  omp_nest_lock_25_arg (lock) = NULL;
+#endif
+}
+
+void
+gomp_set_lock__25 (omp_lock_25_arg_t lock)
+{
+  gomp_set_lock_25 (omp_lock_25_arg (lock));
+}
+
+void
+gomp_set_nest_lock__25 (omp_nest_lock_25_arg_t lock)
+{
+  gomp_set_nest_lock_25 (omp_nest_lock_25_arg (lock));
+}
+
+void
+gomp_unset_lock__25 (omp_lock_25_arg_t lock)
+{
+  gomp_unset_lock_25 (omp_lock_25_arg (lock));
+}
+
+void
+gomp_unset_nest_lock__25 (omp_nest_lock_25_arg_t lock)
+{
+  gomp_unset_nest_lock_25 (omp_nest_lock_25_arg (lock));
+}
+
+int32_t
+gomp_test_lock__25 (omp_lock_25_arg_t lock)
+{
+  return gomp_test_lock_25 (omp_lock_25_arg (lock));
+}
+
+int32_t
+gomp_test_nest_lock__25 (omp_nest_lock_25_arg_t lock)
+{
+  return gomp_test_nest_lock_25 (omp_nest_lock_25_arg (lock));
+}
+
+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_)
+#endif
+
+void
 omp_set_dynamic_ (const int32_t *set)
 {
   omp_set_dynamic (*set);
@@ -188,12 +302,6 @@ omp_in_parallel_ (void)
 }
 
 int32_t
-omp_test_lock_ (omp_lock_arg_t lock)
-{
-  return omp_test_lock (omp_lock_arg (lock));
-}
-
-int32_t
 omp_get_max_threads_ (void)
 {
   return omp_get_max_threads ();
@@ -217,12 +325,6 @@ omp_get_thread_num_ (void)
   return omp_get_thread_num ();
 }
 
-int32_t
-omp_test_nest_lock_ (omp_nest_lock_arg_t lock)
-{
-  return omp_test_nest_lock (omp_nest_lock_arg (lock));
-}
-
 double
 omp_get_wtick_ (void)
 {
--- configure.ac	(revision 132481)
+++ configure.ac	(working copy)
@@ -227,6 +227,11 @@ LIBGOMP_CHECK_ATTRIBUTE_DLLEXPORT
 LIBGOMP_CHECK_ATTRIBUTE_ALIAS
 LIBGOMP_ENABLE_SYMVERS
 
+if test $enable_symvers = gnu; then
+  AC_DEFINE(LIBGOMP_GNU_SYMBOL_VERSIONING, 1,
+	    [Define to 1 if GNU symbol versioning is used for libgomp.])
+fi
+
 # Get target configury.
 . ${srcdir}/configure.tgt
 CFLAGS="$save_CFLAGS $XCFLAGS"
@@ -271,7 +276,7 @@ AM_CONDITIONAL([USE_FORTRAN], [test "$ac
 save_CFLAGS="$CFLAGS"
 for i in $config_path; do
   if test -f $srcdir/config/$i/omp-lock.h; then
-    CFLAGS="$CFLAGS -include $srcdir/config/$i/omp-lock.h"
+    CFLAGS="$CFLAGS -include confdefs.h -include $srcdir/config/$i/omp-lock.h"
     break
   fi
 done
@@ -281,6 +286,11 @@ _AC_COMPUTE_INT([sizeof (omp_lock_t)], [
 _AC_COMPUTE_INT([__alignof (omp_lock_t)], [OMP_LOCK_ALIGN])
 _AC_COMPUTE_INT([sizeof (omp_nest_lock_t)], [OMP_NEST_LOCK_SIZE])
 _AC_COMPUTE_INT([__alignof (omp_nest_lock_t)], [OMP_NEST_LOCK_ALIGN])
+_AC_COMPUTE_INT([sizeof (omp_lock_25_t)], [OMP_LOCK_25_SIZE],,
+  [AC_MSG_ERROR([unsupported system, cannot find sizeof (omp_lock_25_t)])])
+_AC_COMPUTE_INT([__alignof (omp_lock_25_t)], [OMP_LOCK_25_ALIGN])
+_AC_COMPUTE_INT([sizeof (omp_nest_lock_25_t)], [OMP_NEST_LOCK_25_SIZE])
+_AC_COMPUTE_INT([__alignof (omp_nest_lock_25_t)], [OMP_NEST_LOCK_25_ALIGN])
 
 # If the lock fits in an integer, then arrange for Fortran to use that
 # integer.  If it doesn't, then arrange for Fortran to use a pointer.
@@ -295,6 +305,14 @@ fi
 if test $OMP_NEST_LOCK_SIZE -gt 8 || test $OMP_NEST_LOCK_ALIGN -gt $OMP_NEST_LOCK_SIZE; then
   OMP_NEST_LOCK_KIND=8
 fi
+OMP_LOCK_25_KIND=$OMP_LOCK_25_SIZE
+OMP_NEST_LOCK_25_KIND=$OMP_NEST_LOCK_25_SIZE
+if test $OMP_LOCK_25_SIZE -gt 8 || test $OMP_LOCK_25_ALIGN -gt $OMP_LOCK_25_SIZE; then
+  OMP_LOCK_25_KIND=8
+fi
+if test $OMP_NEST_LOCK_25_SIZE -gt 8 || test $OMP_NEST_LOCK_25_ALIGN -gt $OMP_NEST_LOCK_25_SIZE; then
+  OMP_NEST_LOCK_25_KIND=8
+fi
 
 AC_SUBST(OMP_LOCK_SIZE)
 AC_SUBST(OMP_LOCK_ALIGN)
@@ -302,6 +320,12 @@ AC_SUBST(OMP_NEST_LOCK_SIZE)
 AC_SUBST(OMP_NEST_LOCK_ALIGN)
 AC_SUBST(OMP_LOCK_KIND)
 AC_SUBST(OMP_NEST_LOCK_KIND)
+AC_SUBST(OMP_LOCK_25_SIZE)
+AC_SUBST(OMP_LOCK_25_ALIGN)
+AC_SUBST(OMP_NEST_LOCK_25_SIZE)
+AC_SUBST(OMP_NEST_LOCK_25_ALIGN)
+AC_SUBST(OMP_LOCK_25_KIND)
+AC_SUBST(OMP_NEST_LOCK_25_KIND)
 CFLAGS="$save_CFLAGS"
 
 AC_CONFIG_FILES(omp.h omp_lib.h omp_lib.f90 libgomp_f.h)
--- libgomp.map	(revision 132481)
+++ libgomp.map	(working copy)
@@ -80,6 +80,26 @@ OMP_3.0 {
 	omp_get_team_size_8_;
 	omp_get_active_level;
 	omp_get_active_level_;
+	omp_init_lock;
+	omp_init_nest_lock;
+	omp_destroy_lock;
+	omp_destroy_nest_lock;
+	omp_set_lock;
+	omp_set_nest_lock;
+	omp_unset_lock;
+	omp_unset_nest_lock;
+	omp_test_lock;
+	omp_test_nest_lock;
+	omp_destroy_lock_;
+	omp_destroy_nest_lock_;
+	omp_init_lock_;
+	omp_init_nest_lock_;
+	omp_set_lock_;
+	omp_set_nest_lock_;
+	omp_test_lock_;
+	omp_test_nest_lock_;
+	omp_unset_lock_;
+	omp_unset_nest_lock_;
 } OMP_2.0;
 
 GOMP_1.0 {
--- libgomp.h	(revision 132769)
+++ libgomp.h	(working copy)
@@ -380,6 +380,53 @@ extern void gomp_work_share_end_nowait (
 #define _LIBGOMP_OMP_LOCK_DEFINED 1
 #include "omp.h.in"
 
+#if !defined (HAVE_ATTRIBUTE_VISIBILITY) \
+    || !defined (HAVE_ATTRIBUTE_ALIAS) \
+    || !defined (PIC)
+# undef LIBGOMP_GNU_SYMBOL_VERSIONING
+#endif
+
+#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
+extern void gomp_init_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
+extern void gomp_destroy_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
+extern void gomp_set_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
+extern void gomp_unset_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
+extern int gomp_test_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
+extern void gomp_init_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void gomp_destroy_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void gomp_set_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void gomp_unset_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern int gomp_test_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
+
+extern void gomp_init_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_destroy_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_set_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_unset_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
+extern int gomp_test_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_init_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_set_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
+extern void gomp_unset_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
+extern int gomp_test_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
+
+# define strong_alias(fn, al) \
+  extern __typeof (fn) al __attribute__ ((alias (#fn)));
+# define omp_lock_symver(fn) \
+  __asm (".symver g" #fn "_30, " #fn "@@OMP_3.0"); \
+  __asm (".symver g" #fn "_25, " #fn "@OMP_1.0");
+#else
+# define gomp_init_lock_30 omp_init_lock
+# define gomp_destroy_lock_30 omp_destroy_lock
+# define gomp_set_lock_30 omp_set_lock
+# define gomp_unset_lock_30 omp_unset_lock
+# define gomp_test_lock_30 omp_test_lock
+# define gomp_init_nest_lock_30 omp_init_nest_lock
+# define gomp_destroy_nest_lock_30 omp_destroy_nest_lock
+# define gomp_set_nest_lock_30 omp_set_nest_lock
+# define gomp_unset_nest_lock_30 omp_unset_nest_lock
+# define gomp_test_nest_lock_30 omp_test_nest_lock
+#endif
+
 #ifdef HAVE_ATTRIBUTE_VISIBILITY
 # define attribute_hidden __attribute__ ((visibility ("hidden")))
 #else
--- testsuite/libgomp.fortran/lock-1.f90	(revision 0)
+++ testsuite/libgomp.fortran/lock-1.f90	(revision 0)
@@ -0,0 +1,24 @@
+! { dg-do run }
+
+  use omp_lib
+
+  integer (kind = omp_nest_lock_kind) :: lock
+  logical :: l
+
+  l = .false.
+  call omp_init_nest_lock (lock)
+  if (omp_test_nest_lock (lock) .ne. 1) call abort
+  if (omp_test_nest_lock (lock) .ne. 2) call abort
+!$omp parallel if (.false.) reduction (.or.:l)
+  ! In OpenMP 2.5 this was supposed to return 3,
+  ! but in OpenMP 3.0 the parallel region has a different
+  ! task and omp_*_lock_t are owned by tasks, not by threads.
+  if (omp_test_nest_lock (lock) .ne. 0) l = .true.
+!$omp end parallel
+  if (l) call abort
+  if (omp_test_nest_lock (lock) .ne. 3) call abort
+  call omp_unset_nest_lock (lock)
+  call omp_unset_nest_lock (lock)
+  call omp_unset_nest_lock (lock)
+  call omp_destroy_nest_lock (lock)
+end
--- testsuite/libgomp.fortran/lock-2.f90	(revision 0)
+++ testsuite/libgomp.fortran/lock-2.f90	(revision 0)
@@ -0,0 +1,24 @@
+! { dg-do run }
+
+  use omp_lib
+
+  integer (kind = omp_nest_lock_kind) :: lock
+  logical :: l
+
+  l = .false.
+  call omp_init_nest_lock (lock)
+!$omp parallel num_threads (1) reduction (.or.:l)
+  if (omp_test_nest_lock (lock) .ne. 1) call abort
+  if (omp_test_nest_lock (lock) .ne. 2) call abort
+!$omp task if (.false.) shared (lock, l)
+  if (omp_test_nest_lock (lock) .ne. 0) l = .true.
+!$omp end task
+!$omp taskwait
+  if (omp_test_nest_lock (lock) .ne. 3) l = .true.
+  call omp_unset_nest_lock (lock)
+  call omp_unset_nest_lock (lock)
+  call omp_unset_nest_lock (lock)
+!$omp end parallel
+  if (l) call abort
+  call omp_destroy_nest_lock (lock)
+end
--- testsuite/libgomp.c/lock-1.c	(revision 0)
+++ testsuite/libgomp.c/lock-1.c	(revision 0)
@@ -0,0 +1,31 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  int l = 0;
+  omp_nest_lock_t lock;
+  omp_init_nest_lock (&lock);
+  if (omp_test_nest_lock (&lock) != 1)
+    abort ();
+  if (omp_test_nest_lock (&lock) != 2)
+    abort ();
+#pragma omp parallel if (0) reduction (+:l)
+  {
+    /* In OpenMP 2.5 this was supposed to return 3,
+       but in OpenMP 3.0 the parallel region has a different
+       task and omp_*_lock_t are owned by tasks, not by threads.  */
+    if (omp_test_nest_lock (&lock) != 0)
+      l++;
+  }
+  if (l)
+    abort ();
+  if (omp_test_nest_lock (&lock) != 3)
+    abort ();
+  omp_unset_nest_lock (&lock);
+  omp_unset_nest_lock (&lock);
+  omp_unset_nest_lock (&lock);
+  omp_destroy_nest_lock (&lock);
+  return 0;
+}
--- testsuite/libgomp.c/lock-2.c	(revision 0)
+++ testsuite/libgomp.c/lock-2.c	(revision 0)
@@ -0,0 +1,32 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  int l = 0;
+  omp_nest_lock_t lock;
+  omp_init_nest_lock (&lock);
+#pragma omp parallel reduction (+:l) num_threads (1)
+  {
+    if (omp_test_nest_lock (&lock) != 1)
+      l++;
+    if (omp_test_nest_lock (&lock) != 2)
+      l++;
+  #pragma omp task if (0) shared (lock, l)
+    {
+      if (omp_test_nest_lock (&lock) != 0)
+	l++;
+    }
+  #pragma omp taskwait
+    if (omp_test_nest_lock (&lock) != 3)
+      l++;
+    omp_unset_nest_lock (&lock);
+    omp_unset_nest_lock (&lock);
+    omp_unset_nest_lock (&lock);
+  }
+  if (l)
+    abort ();
+  omp_destroy_nest_lock (&lock);
+  return 0;
+}
--- config/linux/omp-lock.h	(revision 132481)
+++ config/linux/omp-lock.h	(working copy)
@@ -3,8 +3,10 @@
    structures without polluting the namespace.
 
    When using the Linux futex primitive, non-recursive locks require
-   only one int.  Recursive locks require we identify the owning thread
-   and so require two ints.  */
+   only one int.  Recursive locks require we identify the owning task
+   and so require one int and a pointer.  */
 
 typedef int omp_lock_t;
-typedef struct { int owner, count; } omp_nest_lock_t;
+typedef struct { int lock, count; void *owner; } omp_nest_lock_t;
+typedef int omp_lock_25_t;
+typedef struct { int owner, count; } omp_nest_lock_25_t;
--- config/linux/lock.c	(revision 132481)
+++ config/linux/lock.c	(working copy)
@@ -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).
@@ -40,36 +40,99 @@
    have the same form.  Re-use it.  */
 
 void
-omp_init_lock (omp_lock_t *lock)
+gomp_init_lock_30 (omp_lock_t *lock)
 {
   gomp_mutex_init (lock);
 }
 
 void
-omp_destroy_lock (omp_lock_t *lock)
+gomp_destroy_lock_30 (omp_lock_t *lock)
 {
   gomp_mutex_destroy (lock);
 }
 
 void
-omp_set_lock (omp_lock_t *lock)
+gomp_set_lock_30 (omp_lock_t *lock)
 {
   gomp_mutex_lock (lock);
 }
 
 void
-omp_unset_lock (omp_lock_t *lock)
+gomp_unset_lock_30 (omp_lock_t *lock)
 {
   gomp_mutex_unlock (lock);
 }
 
 int
-omp_test_lock (omp_lock_t *lock)
+gomp_test_lock_30 (omp_lock_t *lock)
 {
   return __sync_bool_compare_and_swap (lock, 0, 1);
 }
 
-/* The external recursive omp_nest_lock_t form requires additional work.  */
+void
+gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
+{
+  memset (lock, '\0', sizeof (*lock));
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+}
+
+void
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+  void *me = gomp_icv ();
+
+  if (lock->owner != me)
+    {
+      gomp_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;
+      gomp_mutex_unlock (&lock->lock);
+    }
+}
+
+int
+gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
+{
+  void *me = gomp_icv ();
+
+  if (lock->owner == me)
+    return ++lock->count;
+
+  if (__sync_bool_compare_and_swap (&lock->lock, 0, 1))
+    {
+      lock->owner = me;
+      lock->count = 1;
+      return 1;
+    }
+
+  return 0;
+}
+
+#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
+/* gomp_mutex_* can be safely locked in one thread and
+   unlocked in another thread, so the OpenMP 2.5 and OpenMP 3.0
+   non-nested locks can be the same.  */
+strong_alias (gomp_init_lock_30, gomp_init_lock_25)
+strong_alias (gomp_destroy_lock_30, gomp_destroy_lock_25)
+strong_alias (gomp_set_lock_30, gomp_set_lock_25)
+strong_alias (gomp_unset_lock_30, gomp_unset_lock_25)
+strong_alias (gomp_test_lock_30, gomp_test_lock_25)
+
+/* The external recursive omp_nest_lock_25_t form requires additional work.  */
 
 /* We need an integer to uniquely identify this thread.  Most generally
    this is the thread's TID, which ideally we'd get this straight from
@@ -85,17 +148,17 @@ omp_test_lock (omp_lock_t *lock)
    always available directly.  Make do with the gomp_thread pointer
    since it's handy.  */
 
-#if !defined (HAVE_TLS)
+# if !defined (HAVE_TLS)
 static inline int gomp_tid (void)
 {
   return syscall (SYS_gettid);
 }
-#elif !defined(__LP64__)
+# elif !defined(__LP64__)
 static inline int gomp_tid (void)
 {
   return (int) gomp_thread ();
 }
-#else
+# else
 static __thread int tid_cache;
 static inline int gomp_tid (void)
 {
@@ -104,22 +167,22 @@ static inline int gomp_tid (void)
     tid_cache = tid = syscall (SYS_gettid);
   return tid;
 }
-#endif
+# endif
 
 
 void
-omp_init_nest_lock (omp_nest_lock_t *lock)
+gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
   memset (lock, 0, sizeof (lock));
 }
 
 void
-omp_destroy_nest_lock (omp_nest_lock_t *lock)
+gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
 }
 
 void
-omp_set_nest_lock (omp_nest_lock_t *lock)
+gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
   int otid, tid = gomp_tid ();
 
@@ -142,7 +205,7 @@ omp_set_nest_lock (omp_nest_lock_t *lock
 }
 
 void
-omp_unset_nest_lock (omp_nest_lock_t *lock)
+gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
   /* ??? Validate that we own the lock here.  */
 
@@ -154,7 +217,7 @@ omp_unset_nest_lock (omp_nest_lock_t *lo
 }
 
 int
-omp_test_nest_lock (omp_nest_lock_t *lock)
+gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
   int otid, tid = gomp_tid ();
 
@@ -170,6 +233,19 @@ omp_test_nest_lock (omp_nest_lock_t *loc
   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)
@@ -180,3 +256,5 @@ ialias (omp_unset_lock)
 ialias (omp_unset_nest_lock)
 ialias (omp_test_lock)
 ialias (omp_test_nest_lock)
+
+#endif
--- config/posix95/omp-lock.h	(revision 132481)
+++ config/posix95/omp-lock.h	(working copy)
@@ -6,12 +6,16 @@
    same PTHREADS primitive.  */
 
 #include <pthread.h>
+#include <semaphore.h>
 
+typedef pthread_mutex_t omp_lock_25_t;
+typedef struct { pthread_mutex_t lock; pthread_t owner; 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;
-  pthread_t owner;
-  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
--- config/posix95/lock.c	(revision 132481)
+++ config/posix95/lock.c	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2006, 2008 Free Software Foundation, Inc.
 
    This file is part of the GNU OpenMP Library (libgomp).
 
@@ -33,39 +33,212 @@
 
 #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->owner = NULL;
+  lock->count = 0;
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+  pthread_mutex_destroy (&lock->lock);
+}
 
 void
-omp_init_lock (omp_lock_t *lock)
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+  void *me = gomp_icv ();
+
+  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)
+{
+  lock->count--;
+
+  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 ();
+
+  if (lock->owner != me)
+    {
+      if (pthread_mutex_trylock (&lock->lock) != 0)
+	return 0;
+      lock->owner = me;
+    }
+
+  return ++lock->count;
+}
+
+#else
+
+void
+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 ();
+
+  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 ();
+
+  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_mutex_init (&lock->lock, NULL);
   lock->owner = (pthread_t) 0;
@@ -73,13 +246,13 @@ omp_init_nest_lock (omp_nest_lock_t *loc
 }
 
 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_t me = pthread_self ();
 
@@ -93,7 +266,7 @@ omp_set_nest_lock (omp_nest_lock_t *lock
 }
 
 void
-omp_unset_nest_lock (omp_nest_lock_t *lock)
+gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
   lock->count--;
 
@@ -105,7 +278,7 @@ omp_unset_nest_lock (omp_nest_lock_t *lo
 }
 
 int
-omp_test_nest_lock (omp_nest_lock_t *lock)
+gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
 {
   pthread_t me = pthread_self ();
 
@@ -119,6 +292,19 @@ omp_test_nest_lock (omp_nest_lock_t *loc
   return ++lock->count;
 }
 
+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)
@@ -129,3 +315,5 @@ ialias (omp_unset_lock)
 ialias (omp_unset_nest_lock)
 ialias (omp_test_lock)
 ialias (omp_test_nest_lock)
+
+#endif
--- config/posix/omp-lock.h	(revision 132481)
+++ config/posix/omp-lock.h	(working copy)
@@ -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
--- config/posix/lock.c	(revision 132481)
+++ config/posix/lock.c	(working copy)
@@ -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 ();
+
+  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 ();
+
+  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 ();
+
+  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 ();
+
+  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 *loc
 }
 
 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

	Jakub



More information about the Gcc-patches mailing list