]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Update after gnulib changed.
authorBruno Haible <bruno@clisp.org>
Sat, 20 Jul 2019 12:25:21 +0000 (14:25 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 13 Apr 2020 08:05:51 +0000 (10:05 +0200)
* autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC_COMMON_DEPENDENCIES): Add
windows-rwlock.
* gettext-runtime/intl/windows-rwlock.h: New file, from gnulib.
* gettext-runtime/intl/windows-rwlock.c: New file, from gnulib.
* gettext-runtime/intl/windows-initguard.h: New file, from gnulib.
* gettext-runtime/intl/windows-spinlock.h: Remove file.
* gettext-runtime/intl/lock.h: Update from gnulib.
* gettext-runtime/intl/lock.c: Likewise.
* gettext-runtime/intl/verify.h: Likewise.
* gettext-runtime/intl/windows-mutex.h: Likewise.
* gettext-runtime/intl/windows-recmutex.h: Likewise.
* gettext-runtime/intl/Makefile.am (EXTRA_DIST): Add windows-rwlock.h,
windows-initguard.h. Remove windows-spinlock.h.
(LIBINTLSOURCES): Conditionally add windows-rwlock.c.
(windows-rwlock.lo): New rule.
(*.lo): Update dependencies.
* Makefile.am (distcheck-hook): Check that gettext-runtime/intl/windows-*.[hc]
are up-to-date.
* gnulib-local/lib/libxml/threads.c: Test HAVE_PTHREAD_H, HAVE_WIN32_THREADS,
HAVE_BEOS_THREADS only if LIBXML_THREAD_ENABLED is defined; otherwise use a
fallback suitable for single-threaded applications.

13 files changed:
.gitignore
Makefile.am
autogen.sh
gettext-runtime/intl/Makefile.am
gettext-runtime/intl/lock.c
gettext-runtime/intl/lock.h
gettext-runtime/intl/verify.h
gettext-runtime/intl/windows-initguard.h [moved from gettext-runtime/intl/windows-spinlock.h with 80% similarity]
gettext-runtime/intl/windows-mutex.h
gettext-runtime/intl/windows-recmutex.h
gettext-runtime/intl/windows-rwlock.c [new file with mode: 0644]
gettext-runtime/intl/windows-rwlock.h [new file with mode: 0644]
gnulib-local/lib/libxml/threads.c

index db259acf16066181ec507ba615c023bf1dd6757a..81a02146b12b6dddcc7f6231523ba87e0281fa36 100644 (file)
 /gettext-tools/libgettextpo/wctype-h.c
 /gettext-tools/libgettextpo/wctype.in.h
 /gettext-tools/libgettextpo/wcwidth.c
+/gettext-tools/libgettextpo/windows-initguard.h
 /gettext-tools/libgettextpo/windows-mutex.c
 /gettext-tools/libgettextpo/windows-mutex.h
 /gettext-tools/libgettextpo/windows-once.c
 /gettext-tools/libgettextpo/windows-once.h
 /gettext-tools/libgettextpo/windows-recmutex.c
 /gettext-tools/libgettextpo/windows-recmutex.h
-/gettext-tools/libgettextpo/windows-spinlock.h
+/gettext-tools/libgettextpo/windows-rwlock.c
+/gettext-tools/libgettextpo/windows-rwlock.h
 /gettext-tools/libgettextpo/windows-tls.c
 /gettext-tools/libgettextpo/windows-tls.h
 /gettext-tools/libgettextpo/xalloc-oversized.h
index 5aeb7adf358cd4a6ea72346235ce0a43ed52e94a..c2f634e5997762eadf90153b23553466337c3a89 100644 (file)
@@ -95,13 +95,15 @@ distcheck-hook:
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/lock.c | md5sum`" = "`sed -e 1,15d -e 's,glthread/,,g' $(srcdir)/gettext-tools/gnulib-lib/glthread/lock.c | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/threadlib.c | md5sum`" = "`sed -e 1,15d $(srcdir)/gettext-tools/gnulib-lib/glthread/threadlib.c | md5sum`"
        test "`sed 1,16d $(srcdir)/gettext-runtime/intl/verify.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/verify.h | md5sum`"
+       test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-initguard.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-initguard.h | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-mutex.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-mutex.h | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-mutex.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-mutex.c | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-once.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-once.h | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-once.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-once.c | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-recmutex.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-recmutex.h | md5sum`"
        test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-recmutex.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-recmutex.c | md5sum`"
-       test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-spinlock.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-spinlock.h | md5sum`"
+       test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-rwlock.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-rwlock.h | md5sum`"
+       test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-rwlock.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-rwlock.c | md5sum`"
        cmp -s $(srcdir)/gettext-runtime/intl/printf-args.h $(srcdir)/gettext-runtime/libasprintf/printf-args.h
        cmp -s $(srcdir)/gettext-runtime/intl/printf-args.c $(srcdir)/gettext-runtime/libasprintf/printf-args.c
        cmp -s $(srcdir)/gettext-runtime/intl/printf-parse.h $(srcdir)/gettext-runtime/libasprintf/printf-parse.h
index c0ce815bab04d387119b19ec4c851f965b14d3b5..c566d713091aa5ac260d4ebac5c85c993212a6f6 100755 (executable)
@@ -250,6 +250,7 @@ if ! $skip_gnulib; then
     windows-mutex
     windows-once
     windows-recmutex
+    windows-rwlock
   '
   GNULIB_MODULES_TOOLS_OTHER='
     gettext-tools-misc
index 9cb70a1f5b97d9526a4c2fe24524ede6816b2903..6063a920666868bad65433bc17dc7ed0fa1db341 100644 (file)
@@ -81,7 +81,7 @@ EXTRA_DIST += \
   plural-exp.h \
   eval-plural.h \
   localcharset.h \
-  lock.h windows-spinlock.h windows-mutex.h windows-recmutex.h windows-once.h \
+  lock.h windows-mutex.h windows-rwlock.h windows-recmutex.h windows-once.h windows-initguard.h \
   relocatable.h \
   flexmember.h \
   localename-table.in.h \
@@ -129,6 +129,7 @@ LIBINTLSOURCES = \
 if WINDOWS_NATIVE
 LIBINTLSOURCES += \
   windows-mutex.c \
+  windows-rwlock.c \
   windows-recmutex.c \
   windows-once.c
 endif
@@ -281,6 +282,8 @@ intl-compat.lo: $(srcdir)/intl-compat.c
        $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/intl-compat.c
 windows-mutex.lo: $(srcdir)/windows-mutex.c
        $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-mutex.c
+windows-rwlock.lo: $(srcdir)/windows-rwlock.c
+       $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-rwlock.c
 windows-recmutex.lo: $(srcdir)/windows-recmutex.c
        $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-recmutex.c
 windows-once.lo: $(srcdir)/windows-once.c
@@ -294,39 +297,40 @@ if USE_INCLUDED_LIBINTL
 PLURAL_DEPS += libintl.h
 endif
 
-bindtextdom.lo:      ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-dcgettext.lo:        ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-dgettext.lo:         ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-gettext.lo:          ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-finddomain.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
+bindtextdom.lo:      ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+dcgettext.lo:        ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+dgettext.lo:         ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+gettext.lo:          ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+finddomain.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
 hash-string.lo:      ../config.h $(srcdir)/hash-string.h
-loadmsgcat.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/hash-string.h $(srcdir)/plural-exp.h
-localealias.lo:      ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/relocatable.h
-textdomain.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
+loadmsgcat.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/hash-string.h $(srcdir)/plural-exp.h
+localealias.lo:      ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/relocatable.h
+textdomain.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
 l10nflist.lo:        ../config.h $(srcdir)/loadinfo.h
 explodename.lo:      ../config.h $(srcdir)/loadinfo.h
-dcigettext.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/localcharset.h $(srcdir)/plural-exp.h $(srcdir)/hash-string.h $(srcdir)/tsearch.h $(srcdir)/tsearch.c $(srcdir)/eval-plural.h
-dcngettext.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-dngettext.lo:        ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-ngettext.lo:         ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
+dcigettext.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/localcharset.h $(srcdir)/plural-exp.h $(srcdir)/hash-string.h $(srcdir)/tsearch.h $(srcdir)/tsearch.c $(srcdir)/eval-plural.h
+dcngettext.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+dngettext.lo:        ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+ngettext.lo:         ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
 plural.lo:           ../config.h $(srcdir)/plural-exp.h $(PLURAL_DEPS)
 plural-exp.lo:       ../config.h $(srcdir)/plural-exp.h
 localcharset.lo:     ../config.h $(srcdir)/localcharset.h
 threadlib.lo:        ../config.h
-lock.lo:             ../config.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
+lock.lo:             ../config.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
 relocatable.lo:      ../config.h $(srcdir)/relocatable.h
 langprefs.lo:        ../config.h
-localename.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/flexmember.h localename-table.h
-localename-table.lo: ../config.h localename-table.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-log.lo:              ../config.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
+localename.lo:       ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/flexmember.h localename-table.h
+localename-table.lo: ../config.h localename-table.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+log.lo:              ../config.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
 printf.lo:           ../config.h $(srcdir)/printf-args.c $(srcdir)/printf-args.h $(srcdir)/printf-parse.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/xsize.h $(srcdir)/vasnprintf.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/verify.h
-setlocale.lo:        ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
+setlocale.lo:        ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
 version.lo:          ../config.h libgnuintl.h
 xsize.lo:            ../config.h $(srcdir)/xsize.h
 osdep.lo:            ../config.h $(srcdir)/intl-exports.c $(srcdir)/os2compat.c
-intl-compat.lo:      ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-spinlock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h
-windows-mutex.lo:    ../config.h $(srcdir)/windows-mutex.h $(srcdir)/windows-spinlock.h
-windows-recmutex.lo: ../config.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-spinlock.h
+intl-compat.lo:      ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+windows-mutex.lo:    ../config.h $(srcdir)/windows-mutex.h $(srcdir)/windows-initguard.h
+windows-rwlock.lo:   ../config.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-initguard.h
+windows-recmutex.lo: ../config.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-initguard.h
 windows-once.lo:     ../config.h $(srcdir)/windows-once.h
 
 # Version information according to Woe32 conventions.
index ad2794baa00d43bfac257bbda79ca865db98e42e..5640111781f0dcc3eb55f822d9ed3fba3442a532 100644 (file)
@@ -15,8 +15,7 @@
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
-   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
-   gthr-win32.h.  */
+   Based on GCC's gthr-posix.h, gthr-posix95.h.  */
 
 #include <config.h>
 
@@ -500,579 +499,8 @@ glthread_once_singlethreaded (pthread_once_t *once_control)
 
 /* ========================================================================= */
 
-#if USE_PTH_THREADS
-
-/* Use the GNU Pth threads library.  */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-# if !HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER
-
-int
-glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
-{
-  if (!pth_mutex_init (&lock->lock))
-    return errno;
-  if (!pth_cond_init (&lock->waiting_readers))
-    return errno;
-  if (!pth_cond_init (&lock->waiting_writers))
-    return errno;
-  lock->waiting_writers_count = 0;
-  lock->runcount = 0;
-  lock->initialized = 1;
-  return 0;
-}
-
-int
-glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
-{
-  if (!lock->initialized)
-    glthread_rwlock_init_multithreaded (lock);
-  if (!pth_mutex_acquire (&lock->lock, 0, NULL))
-    return errno;
-  /* Test whether only readers are currently running, and whether the runcount
-     field will not overflow, and whether no writer is waiting.  The latter
-     condition is because POSIX recommends that "write locks shall take
-     precedence over read locks", to avoid "writer starvation".  */
-  while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
-    {
-      /* This thread has to wait for a while.  Enqueue it among the
-         waiting_readers.  */
-      if (!pth_cond_await (&lock->waiting_readers, &lock->lock, NULL))
-        {
-          int err = errno;
-          pth_mutex_release (&lock->lock);
-          return err;
-        }
-    }
-  lock->runcount++;
-  return (!pth_mutex_release (&lock->lock) ? errno : 0);
-}
-
-int
-glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
-{
-  if (!lock->initialized)
-    glthread_rwlock_init_multithreaded (lock);
-  if (!pth_mutex_acquire (&lock->lock, 0, NULL))
-    return errno;
-  /* Test whether no readers or writers are currently running.  */
-  while (!(lock->runcount == 0))
-    {
-      /* This thread has to wait for a while.  Enqueue it among the
-         waiting_writers.  */
-      lock->waiting_writers_count++;
-      if (!pth_cond_await (&lock->waiting_writers, &lock->lock, NULL))
-        {
-          int err = errno;
-          lock->waiting_writers_count--;
-          pth_mutex_release (&lock->lock);
-          return err;
-        }
-      lock->waiting_writers_count--;
-    }
-  lock->runcount--; /* runcount becomes -1 */
-  return (!pth_mutex_release (&lock->lock) ? errno : 0);
-}
-
-int
-glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
-{
-  int err;
-
-  if (!lock->initialized)
-    return EINVAL;
-  if (!pth_mutex_acquire (&lock->lock, 0, NULL))
-    return errno;
-  if (lock->runcount < 0)
-    {
-      /* Drop a writer lock.  */
-      if (!(lock->runcount == -1))
-        {
-          pth_mutex_release (&lock->lock);
-          return EINVAL;
-        }
-      lock->runcount = 0;
-    }
-  else
-    {
-      /* Drop a reader lock.  */
-      if (!(lock->runcount > 0))
-        {
-          pth_mutex_release (&lock->lock);
-          return EINVAL;
-        }
-      lock->runcount--;
-    }
-  if (lock->runcount == 0)
-    {
-      /* POSIX recommends that "write locks shall take precedence over read
-         locks", to avoid "writer starvation".  */
-      if (lock->waiting_writers_count > 0)
-        {
-          /* Wake up one of the waiting writers.  */
-          if (!pth_cond_notify (&lock->waiting_writers, FALSE))
-            {
-              int err = errno;
-              pth_mutex_release (&lock->lock);
-              return err;
-            }
-        }
-      else
-        {
-          /* Wake up all waiting readers.  */
-          if (!pth_cond_notify (&lock->waiting_readers, TRUE))
-            {
-              int err = errno;
-              pth_mutex_release (&lock->lock);
-              return err;
-            }
-        }
-    }
-  return (!pth_mutex_release (&lock->lock) ? errno : 0);
-}
-
-int
-glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
-{
-  lock->initialized = 0;
-  return 0;
-}
-
-# endif
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-static void
-glthread_once_call (void *arg)
-{
-  void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;
-  void (*initfunction) (void) = *gl_once_temp_addr;
-  initfunction ();
-}
-
-int
-glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void))
-{
-  void (*temp) (void) = initfunction;
-  return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0);
-}
-
-int
-glthread_once_singlethreaded (pth_once_t *once_control)
-{
-  /* We know that pth_once_t is an integer type.  */
-  if (*once_control == PTH_ONCE_INIT)
-    {
-      /* First time use of once_control.  Invert the marker.  */
-      *once_control = ~ PTH_ONCE_INIT;
-      return 1;
-    }
-  else
-    return 0;
-}
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_SOLARIS_THREADS
-
-/* Use the old Solaris threads library.  */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-int
-glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
-{
-  int err;
-
-  err = mutex_init (&lock->mutex, USYNC_THREAD, NULL);
-  if (err != 0)
-    return err;
-  lock->owner = (thread_t) 0;
-  lock->depth = 0;
-  return 0;
-}
-
-int
-glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
-{
-  thread_t self = thr_self ();
-  if (lock->owner != self)
-    {
-      int err;
-
-      err = mutex_lock (&lock->mutex);
-      if (err != 0)
-        return err;
-      lock->owner = self;
-    }
-  if (++(lock->depth) == 0) /* wraparound? */
-    {
-      lock->depth--;
-      return EAGAIN;
-    }
-  return 0;
-}
-
-int
-glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
-{
-  if (lock->owner != thr_self ())
-    return EPERM;
-  if (lock->depth == 0)
-    return EINVAL;
-  if (--(lock->depth) == 0)
-    {
-      lock->owner = (thread_t) 0;
-      return mutex_unlock (&lock->mutex);
-    }
-  else
-    return 0;
-}
-
-int
-glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
-{
-  if (lock->owner != (thread_t) 0)
-    return EBUSY;
-  return mutex_destroy (&lock->mutex);
-}
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-int
-glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void))
-{
-  if (!once_control->inited)
-    {
-      int err;
-
-      /* Use the mutex to guarantee that if another thread is already calling
-         the initfunction, this thread waits until it's finished.  */
-      err = mutex_lock (&once_control->mutex);
-      if (err != 0)
-        return err;
-      if (!once_control->inited)
-        {
-          once_control->inited = 1;
-          initfunction ();
-        }
-      return mutex_unlock (&once_control->mutex);
-    }
-  else
-    return 0;
-}
-
-int
-glthread_once_singlethreaded (gl_once_t *once_control)
-{
-  /* We know that gl_once_t contains an integer type.  */
-  if (!once_control->inited)
-    {
-      /* First time use of once_control.  Invert the marker.  */
-      once_control->inited = ~ 0;
-      return 1;
-    }
-  else
-    return 0;
-}
-
-#endif
-
-/* ========================================================================= */
-
 #if USE_WINDOWS_THREADS
 
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-/* In this file, the waitqueues are implemented as circular arrays.  */
-#define gl_waitqueue_t gl_carray_waitqueue_t
-
-static void
-gl_waitqueue_init (gl_waitqueue_t *wq)
-{
-  wq->array = NULL;
-  wq->count = 0;
-  wq->alloc = 0;
-  wq->offset = 0;
-}
-
-/* Enqueues the current thread, represented by an event, in a wait queue.
-   Returns INVALID_HANDLE_VALUE if an allocation failure occurs.  */
-static HANDLE
-gl_waitqueue_add (gl_waitqueue_t *wq)
-{
-  HANDLE event;
-  unsigned int index;
-
-  if (wq->count == wq->alloc)
-    {
-      unsigned int new_alloc = 2 * wq->alloc + 1;
-      HANDLE *new_array =
-        (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
-      if (new_array == NULL)
-        /* No more memory.  */
-        return INVALID_HANDLE_VALUE;
-      /* Now is a good opportunity to rotate the array so that its contents
-         starts at offset 0.  */
-      if (wq->offset > 0)
-        {
-          unsigned int old_count = wq->count;
-          unsigned int old_alloc = wq->alloc;
-          unsigned int old_offset = wq->offset;
-          unsigned int i;
-          if (old_offset + old_count > old_alloc)
-            {
-              unsigned int limit = old_offset + old_count - old_alloc;
-              for (i = 0; i < limit; i++)
-                new_array[old_alloc + i] = new_array[i];
-            }
-          for (i = 0; i < old_count; i++)
-            new_array[i] = new_array[old_offset + i];
-          wq->offset = 0;
-        }
-      wq->array = new_array;
-      wq->alloc = new_alloc;
-    }
-  /* Whether the created event is a manual-reset one or an auto-reset one,
-     does not matter, since we will wait on it only once.  */
-  event = CreateEvent (NULL, TRUE, FALSE, NULL);
-  if (event == INVALID_HANDLE_VALUE)
-    /* No way to allocate an event.  */
-    return INVALID_HANDLE_VALUE;
-  index = wq->offset + wq->count;
-  if (index >= wq->alloc)
-    index -= wq->alloc;
-  wq->array[index] = event;
-  wq->count++;
-  return event;
-}
-
-/* Notifies the first thread from a wait queue and dequeues it.  */
-static void
-gl_waitqueue_notify_first (gl_waitqueue_t *wq)
-{
-  SetEvent (wq->array[wq->offset + 0]);
-  wq->offset++;
-  wq->count--;
-  if (wq->count == 0 || wq->offset == wq->alloc)
-    wq->offset = 0;
-}
-
-/* Notifies all threads from a wait queue and dequeues them all.  */
-static void
-gl_waitqueue_notify_all (gl_waitqueue_t *wq)
-{
-  unsigned int i;
-
-  for (i = 0; i < wq->count; i++)
-    {
-      unsigned int index = wq->offset + i;
-      if (index >= wq->alloc)
-        index -= wq->alloc;
-      SetEvent (wq->array[index]);
-    }
-  wq->count = 0;
-  wq->offset = 0;
-}
-
-void
-glthread_rwlock_init_func (gl_rwlock_t *lock)
-{
-  InitializeCriticalSection (&lock->lock);
-  gl_waitqueue_init (&lock->waiting_readers);
-  gl_waitqueue_init (&lock->waiting_writers);
-  lock->runcount = 0;
-  lock->guard.done = 1;
-}
-
-int
-glthread_rwlock_rdlock_func (gl_rwlock_t *lock)
-{
-  if (!lock->guard.done)
-    {
-      if (InterlockedIncrement (&lock->guard.started) == 0)
-        /* This thread is the first one to need this lock.  Initialize it.  */
-        glthread_rwlock_init (lock);
-      else
-        {
-          /* Don't let lock->guard.started grow and wrap around.  */
-          InterlockedDecrement (&lock->guard.started);
-          /* Yield the CPU while waiting for another thread to finish
-             initializing this lock.  */
-          while (!lock->guard.done)
-            Sleep (0);
-        }
-    }
-  EnterCriticalSection (&lock->lock);
-  /* Test whether only readers are currently running, and whether the runcount
-     field will not overflow, and whether no writer is waiting.  The latter
-     condition is because POSIX recommends that "write locks shall take
-     precedence over read locks", to avoid "writer starvation".  */
-  if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
-    {
-      /* This thread has to wait for a while.  Enqueue it among the
-         waiting_readers.  */
-      HANDLE event = gl_waitqueue_add (&lock->waiting_readers);
-      if (event != INVALID_HANDLE_VALUE)
-        {
-          DWORD result;
-          LeaveCriticalSection (&lock->lock);
-          /* Wait until another thread signals this event.  */
-          result = WaitForSingleObject (event, INFINITE);
-          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
-            abort ();
-          CloseHandle (event);
-          /* The thread which signalled the event already did the bookkeeping:
-             removed us from the waiting_readers, incremented lock->runcount.  */
-          if (!(lock->runcount > 0))
-            abort ();
-          return 0;
-        }
-      else
-        {
-          /* Allocation failure.  Weird.  */
-          do
-            {
-              LeaveCriticalSection (&lock->lock);
-              Sleep (1);
-              EnterCriticalSection (&lock->lock);
-            }
-          while (!(lock->runcount + 1 > 0));
-        }
-    }
-  lock->runcount++;
-  LeaveCriticalSection (&lock->lock);
-  return 0;
-}
-
-int
-glthread_rwlock_wrlock_func (gl_rwlock_t *lock)
-{
-  if (!lock->guard.done)
-    {
-      if (InterlockedIncrement (&lock->guard.started) == 0)
-        /* This thread is the first one to need this lock.  Initialize it.  */
-        glthread_rwlock_init (lock);
-      else
-        {
-          /* Don't let lock->guard.started grow and wrap around.  */
-          InterlockedDecrement (&lock->guard.started);
-          /* Yield the CPU while waiting for another thread to finish
-             initializing this lock.  */
-          while (!lock->guard.done)
-            Sleep (0);
-        }
-    }
-  EnterCriticalSection (&lock->lock);
-  /* Test whether no readers or writers are currently running.  */
-  if (!(lock->runcount == 0))
-    {
-      /* This thread has to wait for a while.  Enqueue it among the
-         waiting_writers.  */
-      HANDLE event = gl_waitqueue_add (&lock->waiting_writers);
-      if (event != INVALID_HANDLE_VALUE)
-        {
-          DWORD result;
-          LeaveCriticalSection (&lock->lock);
-          /* Wait until another thread signals this event.  */
-          result = WaitForSingleObject (event, INFINITE);
-          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
-            abort ();
-          CloseHandle (event);
-          /* The thread which signalled the event already did the bookkeeping:
-             removed us from the waiting_writers, set lock->runcount = -1.  */
-          if (!(lock->runcount == -1))
-            abort ();
-          return 0;
-        }
-      else
-        {
-          /* Allocation failure.  Weird.  */
-          do
-            {
-              LeaveCriticalSection (&lock->lock);
-              Sleep (1);
-              EnterCriticalSection (&lock->lock);
-            }
-          while (!(lock->runcount == 0));
-        }
-    }
-  lock->runcount--; /* runcount becomes -1 */
-  LeaveCriticalSection (&lock->lock);
-  return 0;
-}
-
-int
-glthread_rwlock_unlock_func (gl_rwlock_t *lock)
-{
-  if (!lock->guard.done)
-    return EINVAL;
-  EnterCriticalSection (&lock->lock);
-  if (lock->runcount < 0)
-    {
-      /* Drop a writer lock.  */
-      if (!(lock->runcount == -1))
-        abort ();
-      lock->runcount = 0;
-    }
-  else
-    {
-      /* Drop a reader lock.  */
-      if (!(lock->runcount > 0))
-        {
-          LeaveCriticalSection (&lock->lock);
-          return EPERM;
-        }
-      lock->runcount--;
-    }
-  if (lock->runcount == 0)
-    {
-      /* POSIX recommends that "write locks shall take precedence over read
-         locks", to avoid "writer starvation".  */
-      if (lock->waiting_writers.count > 0)
-        {
-          /* Wake up one of the waiting writers.  */
-          lock->runcount--;
-          gl_waitqueue_notify_first (&lock->waiting_writers);
-        }
-      else
-        {
-          /* Wake up all waiting readers.  */
-          lock->runcount += lock->waiting_readers.count;
-          gl_waitqueue_notify_all (&lock->waiting_readers);
-        }
-    }
-  LeaveCriticalSection (&lock->lock);
-  return 0;
-}
-
-int
-glthread_rwlock_destroy_func (gl_rwlock_t *lock)
-{
-  if (!lock->guard.done)
-    return EINVAL;
-  if (lock->runcount != 0)
-    return EBUSY;
-  DeleteCriticalSection (&lock->lock);
-  if (lock->waiting_readers.array != NULL)
-    free (lock->waiting_readers.array);
-  if (lock->waiting_writers.array != NULL)
-    free (lock->waiting_writers.array);
-  lock->guard.done = 0;
-  return 0;
-}
-
 #endif
 
 /* ========================================================================= */
index e5cc1a606490c1c0ee6242c71b8ba1e5a1bbf6f7..2c8a5e424ee2138f585482eb44f7d9043ce31562 100644 (file)
@@ -15,8 +15,7 @@
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
-   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
-   gthr-win32.h.  */
+   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */
 
 /* This file contains locking primitives for use with a given thread library.
    It does not contain primitives for creating threads or for other
@@ -82,7 +81,7 @@
 #include <stdlib.h>
 
 #if !defined c11_threads_in_use
-# if HAVE_THREADS_H && (USE_POSIX_THREADS_WEAK || USE_PTH_THREADS_WEAK || USE_SOLARIS_THREADS_WEAK)
+# if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
 #  include <threads.h>
 #  pragma weak thrd_exit
 #  define c11_threads_in_use() (thrd_exit != NULL)
@@ -406,292 +405,13 @@ extern int glthread_once_singlethreaded (pthread_once_t *once_control);
 
 /* ========================================================================= */
 
-#if USE_PTH_THREADS
-
-/* Use the GNU Pth threads library.  */
-
-# include <pth.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# if USE_PTH_THREADS_WEAK
-
-/* Use weak references to the GNU Pth threads library.  */
-
-#  pragma weak pth_mutex_init
-#  pragma weak pth_mutex_acquire
-#  pragma weak pth_mutex_release
-#  pragma weak pth_rwlock_init
-#  pragma weak pth_rwlock_acquire
-#  pragma weak pth_rwlock_release
-#  pragma weak pth_once
-#  pragma weak pth_cond_init
-#  pragma weak pth_cond_await
-#  pragma weak pth_cond_notify
-
-#  pragma weak pth_cancel
-#  define pth_in_use() (pth_cancel != NULL || c11_threads_in_use ())
-
-# else
-
-#  define pth_in_use() 1
-
-# endif
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef pth_mutex_t gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
-    STORAGECLASS pth_mutex_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
-# define gl_lock_initializer \
-    PTH_MUTEX_INIT
-# define glthread_lock_init(LOCK) \
-    (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
-# define glthread_lock_lock(LOCK) \
-    (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
-# define glthread_lock_unlock(LOCK) \
-    (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
-# define glthread_lock_destroy(LOCK) \
-    ((void)(LOCK), 0)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-/* Pth pth_rwlock_acquire always prefers readers.  No autoconf test so far.  */
-# if HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER
-
-typedef pth_rwlock_t gl_rwlock_t;
-#  define gl_rwlock_define(STORAGECLASS, NAME) \
-     STORAGECLASS pth_rwlock_t NAME;
-#  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-     STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
-#  define gl_rwlock_initializer \
-     PTH_RWLOCK_INIT
-#  define glthread_rwlock_init(LOCK) \
-     (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
-#  define glthread_rwlock_rdlock(LOCK) \
-     (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
-#  define glthread_rwlock_wrlock(LOCK) \
-     (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
-#  define glthread_rwlock_unlock(LOCK) \
-     (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
-#  define glthread_rwlock_destroy(LOCK) \
-     ((void)(LOCK), 0)
-
-# else
-
-typedef struct
-        {
-          int initialized;
-          pth_mutex_t lock; /* protects the remaining fields */
-          pth_cond_t waiting_readers; /* waiting readers */
-          pth_cond_t waiting_writers; /* waiting writers */
-          unsigned int waiting_writers_count; /* number of waiting writers */
-          int runcount; /* number of readers running, or -1 when a writer runs */
-        }
-        gl_rwlock_t;
-#  define gl_rwlock_define(STORAGECLASS, NAME) \
-     STORAGECLASS gl_rwlock_t NAME;
-#  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
-#  define gl_rwlock_initializer \
-     { 0 }
-#  define glthread_rwlock_init(LOCK) \
-     (pth_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
-#  define glthread_rwlock_rdlock(LOCK) \
-     (pth_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
-#  define glthread_rwlock_wrlock(LOCK) \
-     (pth_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
-#  define glthread_rwlock_unlock(LOCK) \
-     (pth_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
-#  define glthread_rwlock_destroy(LOCK) \
-     (pth_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
-
-# endif
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-/* In Pth, mutexes are recursive by default.  */
-typedef pth_mutex_t gl_recursive_lock_t;
-#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
-     STORAGECLASS pth_mutex_t NAME;
-#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-     STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
-#  define gl_recursive_lock_initializer \
-     PTH_MUTEX_INIT
-#  define glthread_recursive_lock_init(LOCK) \
-     (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
-#  define glthread_recursive_lock_lock(LOCK) \
-     (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
-#  define glthread_recursive_lock_unlock(LOCK) \
-     (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
-#  define glthread_recursive_lock_destroy(LOCK) \
-     ((void)(LOCK), 0)
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef pth_once_t gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
-    STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
-    (pth_in_use ()                                                             \
-     ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION)                \
-     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
-extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
-extern int glthread_once_singlethreaded (pth_once_t *once_control);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_SOLARIS_THREADS
-
-/* Use the old Solaris threads library.  */
-
-# include <thread.h>
-# include <synch.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# if USE_SOLARIS_THREADS_WEAK
-
-/* Use weak references to the old Solaris threads library.  */
-
-#  pragma weak mutex_init
-#  pragma weak mutex_lock
-#  pragma weak mutex_unlock
-#  pragma weak mutex_destroy
-#  pragma weak rwlock_init
-#  pragma weak rw_rdlock
-#  pragma weak rw_wrlock
-#  pragma weak rw_unlock
-#  pragma weak rwlock_destroy
-#  pragma weak thr_self
-
-#  pragma weak thr_suspend
-#  define thread_in_use() (thr_suspend != NULL || c11_threads_in_use ())
-
-# else
-
-#  define thread_in_use() 1
-
-# endif
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef mutex_t gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
-    STORAGECLASS mutex_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS mutex_t NAME = gl_lock_initializer;
-# define gl_lock_initializer \
-    DEFAULTMUTEX
-# define glthread_lock_init(LOCK) \
-    (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
-# define glthread_lock_lock(LOCK) \
-    (thread_in_use () ? mutex_lock (LOCK) : 0)
-# define glthread_lock_unlock(LOCK) \
-    (thread_in_use () ? mutex_unlock (LOCK) : 0)
-# define glthread_lock_destroy(LOCK) \
-    (thread_in_use () ? mutex_destroy (LOCK) : 0)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-typedef rwlock_t gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
-    STORAGECLASS rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
-    DEFAULTRWLOCK
-# define glthread_rwlock_init(LOCK) \
-    (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
-# define glthread_rwlock_rdlock(LOCK) \
-    (thread_in_use () ? rw_rdlock (LOCK) : 0)
-# define glthread_rwlock_wrlock(LOCK) \
-    (thread_in_use () ? rw_wrlock (LOCK) : 0)
-# define glthread_rwlock_unlock(LOCK) \
-    (thread_in_use () ? rw_unlock (LOCK) : 0)
-# define glthread_rwlock_destroy(LOCK) \
-    (thread_in_use () ? rwlock_destroy (LOCK) : 0)
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-/* Old Solaris threads did not have recursive locks.
-   We have to implement them ourselves.  */
-
-typedef struct
-        {
-          mutex_t mutex;
-          thread_t owner;
-          unsigned long depth;
-        }
-        gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
-    STORAGECLASS gl_recursive_lock_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
-# define gl_recursive_lock_initializer \
-    { DEFAULTMUTEX, (thread_t) 0, 0 }
-# define glthread_recursive_lock_init(LOCK) \
-    (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_lock(LOCK) \
-    (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_unlock(LOCK) \
-    (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_destroy(LOCK) \
-    (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef struct
-        {
-          volatile int inited;
-          mutex_t mutex;
-        }
-        gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
-    STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
-    (thread_in_use ()                                                          \
-     ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION)                \
-     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
-extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
-extern int glthread_once_singlethreaded (gl_once_t *once_control);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
 #if USE_WINDOWS_THREADS
 
 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 # include <windows.h>
 
-# include "windows-spinlock.h"
 # include "windows-mutex.h"
+# include "windows-rwlock.h"
 # include "windows-recmutex.h"
 # include "windows-once.h"
 
@@ -730,48 +450,23 @@ typedef glwthread_mutex_t gl_lock_t;
 
 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 
-/* It is impossible to implement read-write locks using plain locks, without
-   introducing an extra thread dedicated to managing read-write locks.
-   Therefore here we need to use the low-level Event type.  */
-
-typedef struct
-        {
-          HANDLE *array; /* array of waiting threads, each represented by an event */
-          unsigned int count; /* number of waiting threads */
-          unsigned int alloc; /* length of allocated array */
-          unsigned int offset; /* index of first waiting thread in array */
-        }
-        gl_carray_waitqueue_t;
-typedef struct
-        {
-          glwthread_spinlock_t guard; /* protects the initialization */
-          CRITICAL_SECTION lock; /* protects the remaining fields */
-          gl_carray_waitqueue_t waiting_readers; /* waiting readers */
-          gl_carray_waitqueue_t waiting_writers; /* waiting writers */
-          int runcount; /* number of readers running, or -1 when a writer runs */
-        }
-        gl_rwlock_t;
+typedef glwthread_rwlock_t gl_rwlock_t;
 # define gl_rwlock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_rwlock_t NAME;
 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
 # define gl_rwlock_initializer \
-    { GLWTHREAD_SPINLOCK_INIT }
+    GLWTHREAD_RWLOCK_INIT
 # define glthread_rwlock_init(LOCK) \
-    (glthread_rwlock_init_func (LOCK), 0)
+    (glwthread_rwlock_init (LOCK), 0)
 # define glthread_rwlock_rdlock(LOCK) \
-    glthread_rwlock_rdlock_func (LOCK)
+    glwthread_rwlock_rdlock (LOCK)
 # define glthread_rwlock_wrlock(LOCK) \
-    glthread_rwlock_wrlock_func (LOCK)
+    glwthread_rwlock_wrlock (LOCK)
 # define glthread_rwlock_unlock(LOCK) \
-    glthread_rwlock_unlock_func (LOCK)
+    glwthread_rwlock_unlock (LOCK)
 # define glthread_rwlock_destroy(LOCK) \
-    glthread_rwlock_destroy_func (LOCK)
-extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
+    glwthread_rwlock_destroy (LOCK)
 
 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 
@@ -807,7 +502,7 @@ typedef glwthread_once_t gl_once_t;
 
 /* ========================================================================= */
 
-#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS)
+#if !(USE_POSIX_THREADS || USE_WINDOWS_THREADS)
 
 /* Provide dummy implementation if threads are not supported.  */
 
index 33be83c669045d370927a949b75971d2755b64c3..3d0868cd055e61bafed6dc052992571ba0b2efe5 100644 (file)
@@ -259,9 +259,11 @@ template <int w>
 # define __has_builtin(x) 0
 #endif
 
-/* Assume that R always holds.  This lets the compiler optimize
-   accordingly.  R should not have side-effects; it may or may not be
-   evaluated.  Behavior is undefined if R is false.  */
+/* Assume that R always holds.  Behavior is undefined if R is false,
+   fails to evaluate, or has side effects.  Although assuming R can
+   help a compiler generate better code or diagnostics, performance
+   can suffer if R uses hard-to-optimize features such as function
+   calls not inlined by the compiler.  */
 
 #if (__has_builtin (__builtin_unreachable) \
      || 4 < __GNUC__ + (5 <= __GNUC_MINOR__))
similarity index 80%
rename from gettext-runtime/intl/windows-spinlock.h
rename to gettext-runtime/intl/windows-initguard.h
index 6f9cbe15bcf7bf3e5147a1990591ee9763b7c0da..7a3aa6d43f04b04d8d10c8f6ae223faa31b736cc 100644 (file)
@@ -1,4 +1,4 @@
-/* Spinlocks (native Windows implementation).
+/* Init guards, somewhat like spinlocks (native Windows implementation).
    Copyright (C) 2005-2019 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
@@ -17,8 +17,8 @@
 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
    Based on GCC's gthr-win32.h.  */
 
-#ifndef _WINDOWS_SPINLOCK_H
-#define _WINDOWS_SPINLOCK_H
+#ifndef _WINDOWS_INITGUARD_H
+#define _WINDOWS_INITGUARD_H
 
 #define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 #include <windows.h>
@@ -28,8 +28,8 @@ typedef struct
           volatile int done;
           volatile LONG started;
         }
-        glwthread_spinlock_t;
+        glwthread_initguard_t;
 
-#define GLWTHREAD_SPINLOCK_INIT { 0, -1 }
+#define GLWTHREAD_INITGUARD_INIT { 0, -1 }
 
-#endif /* _WINDOWS_SPINLOCK_H */
+#endif /* _WINDOWS_INITGUARD_H */
index 5a1b5506b53a9730a5f05243d64aceb24cfcbd7b..5d3d8e4dbe8292e3d82ebdc0b9ff19ed8b6f8ab7 100644 (file)
 #define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 #include <windows.h>
 
-#include "windows-spinlock.h"
+#include "windows-initguard.h"
 
 typedef struct
         {
-          glwthread_spinlock_t guard; /* protects the initialization */
+          glwthread_initguard_t guard; /* protects the initialization */
           CRITICAL_SECTION lock;
         }
         glwthread_mutex_t;
 
-#define GLWTHREAD_MUTEX_INIT { GLWTHREAD_SPINLOCK_INIT }
+#define GLWTHREAD_MUTEX_INIT { GLWTHREAD_INITGUARD_INIT }
 
 #ifdef __cplusplus
 extern "C" {
index 24eb12c1ee072de45e309293b6cb347a63377db9..2586cc50e4ccd8132066483580c7cb9ca76968ab 100644 (file)
@@ -23,7 +23,7 @@
 #define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 #include <windows.h>
 
-#include "windows-spinlock.h"
+#include "windows-initguard.h"
 
 /* The native Windows documentation says that CRITICAL_SECTION already
    implements a recursive lock.  But we need not rely on it: It's easy to
 
 typedef struct
         {
-          glwthread_spinlock_t guard; /* protects the initialization */
+          glwthread_initguard_t guard; /* protects the initialization */
           DWORD owner;
           unsigned long depth;
           CRITICAL_SECTION lock;
         }
         glwthread_recmutex_t;
 
-#define GLWTHREAD_RECMUTEX_INIT { GLWTHREAD_SPINLOCK_INIT, 0, 0 }
+#define GLWTHREAD_RECMUTEX_INIT { GLWTHREAD_INITGUARD_INIT, 0, 0 }
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/gettext-runtime/intl/windows-rwlock.c b/gettext-runtime/intl/windows-rwlock.c
new file mode 100644 (file)
index 0000000..c69427e
--- /dev/null
@@ -0,0 +1,373 @@
+/* Read-write locks (native Windows implementation).
+   Copyright (C) 2005-2019 Free Software Foundation, Inc.
+
+   This program 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.
+
+   This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+   Based on GCC's gthr-win32.h.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "windows-rwlock.h"
+
+#include <errno.h>
+#include <stdlib.h>
+
+/* In this file, the waitqueues are implemented as circular arrays.  */
+#define glwthread_waitqueue_t glwthread_carray_waitqueue_t
+
+static void
+glwthread_waitqueue_init (glwthread_waitqueue_t *wq)
+{
+  wq->array = NULL;
+  wq->count = 0;
+  wq->alloc = 0;
+  wq->offset = 0;
+}
+
+/* Enqueues the current thread, represented by an event, in a wait queue.
+   Returns INVALID_HANDLE_VALUE if an allocation failure occurs.  */
+static HANDLE
+glwthread_waitqueue_add (glwthread_waitqueue_t *wq)
+{
+  HANDLE event;
+  unsigned int index;
+
+  if (wq->count == wq->alloc)
+    {
+      unsigned int new_alloc = 2 * wq->alloc + 1;
+      HANDLE *new_array =
+        (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
+      if (new_array == NULL)
+        /* No more memory.  */
+        return INVALID_HANDLE_VALUE;
+      /* Now is a good opportunity to rotate the array so that its contents
+         starts at offset 0.  */
+      if (wq->offset > 0)
+        {
+          unsigned int old_count = wq->count;
+          unsigned int old_alloc = wq->alloc;
+          unsigned int old_offset = wq->offset;
+          unsigned int i;
+          if (old_offset + old_count > old_alloc)
+            {
+              unsigned int limit = old_offset + old_count - old_alloc;
+              for (i = 0; i < limit; i++)
+                new_array[old_alloc + i] = new_array[i];
+            }
+          for (i = 0; i < old_count; i++)
+            new_array[i] = new_array[old_offset + i];
+          wq->offset = 0;
+        }
+      wq->array = new_array;
+      wq->alloc = new_alloc;
+    }
+  /* Whether the created event is a manual-reset one or an auto-reset one,
+     does not matter, since we will wait on it only once.  */
+  event = CreateEvent (NULL, TRUE, FALSE, NULL);
+  if (event == INVALID_HANDLE_VALUE)
+    /* No way to allocate an event.  */
+    return INVALID_HANDLE_VALUE;
+  index = wq->offset + wq->count;
+  if (index >= wq->alloc)
+    index -= wq->alloc;
+  wq->array[index] = event;
+  wq->count++;
+  return event;
+}
+
+/* Notifies the first thread from a wait queue and dequeues it.  */
+static void
+glwthread_waitqueue_notify_first (glwthread_waitqueue_t *wq)
+{
+  SetEvent (wq->array[wq->offset + 0]);
+  wq->offset++;
+  wq->count--;
+  if (wq->count == 0 || wq->offset == wq->alloc)
+    wq->offset = 0;
+}
+
+/* Notifies all threads from a wait queue and dequeues them all.  */
+static void
+glwthread_waitqueue_notify_all (glwthread_waitqueue_t *wq)
+{
+  unsigned int i;
+
+  for (i = 0; i < wq->count; i++)
+    {
+      unsigned int index = wq->offset + i;
+      if (index >= wq->alloc)
+        index -= wq->alloc;
+      SetEvent (wq->array[index]);
+    }
+  wq->count = 0;
+  wq->offset = 0;
+}
+
+void
+glwthread_rwlock_init (glwthread_rwlock_t *lock)
+{
+  InitializeCriticalSection (&lock->lock);
+  glwthread_waitqueue_init (&lock->waiting_readers);
+  glwthread_waitqueue_init (&lock->waiting_writers);
+  lock->runcount = 0;
+  lock->guard.done = 1;
+}
+
+int
+glwthread_rwlock_rdlock (glwthread_rwlock_t *lock)
+{
+  if (!lock->guard.done)
+    {
+      if (InterlockedIncrement (&lock->guard.started) == 0)
+        /* This thread is the first one to need this lock.  Initialize it.  */
+        glwthread_rwlock_init (lock);
+      else
+        {
+          /* Don't let lock->guard.started grow and wrap around.  */
+          InterlockedDecrement (&lock->guard.started);
+          /* Yield the CPU while waiting for another thread to finish
+             initializing this lock.  */
+          while (!lock->guard.done)
+            Sleep (0);
+        }
+    }
+  EnterCriticalSection (&lock->lock);
+  /* Test whether only readers are currently running, and whether the runcount
+     field will not overflow, and whether no writer is waiting.  The latter
+     condition is because POSIX recommends that "write locks shall take
+     precedence over read locks", to avoid "writer starvation".  */
+  if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
+    {
+      /* This thread has to wait for a while.  Enqueue it among the
+         waiting_readers.  */
+      HANDLE event = glwthread_waitqueue_add (&lock->waiting_readers);
+      if (event != INVALID_HANDLE_VALUE)
+        {
+          DWORD result;
+          LeaveCriticalSection (&lock->lock);
+          /* Wait until another thread signals this event.  */
+          result = WaitForSingleObject (event, INFINITE);
+          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+            abort ();
+          CloseHandle (event);
+          /* The thread which signalled the event already did the bookkeeping:
+             removed us from the waiting_readers, incremented lock->runcount.  */
+          if (!(lock->runcount > 0))
+            abort ();
+          return 0;
+        }
+      else
+        {
+          /* Allocation failure.  Weird.  */
+          do
+            {
+              LeaveCriticalSection (&lock->lock);
+              Sleep (1);
+              EnterCriticalSection (&lock->lock);
+            }
+          while (!(lock->runcount + 1 > 0));
+        }
+    }
+  lock->runcount++;
+  LeaveCriticalSection (&lock->lock);
+  return 0;
+}
+
+int
+glwthread_rwlock_wrlock (glwthread_rwlock_t *lock)
+{
+  if (!lock->guard.done)
+    {
+      if (InterlockedIncrement (&lock->guard.started) == 0)
+        /* This thread is the first one to need this lock.  Initialize it.  */
+        glwthread_rwlock_init (lock);
+      else
+        {
+          /* Don't let lock->guard.started grow and wrap around.  */
+          InterlockedDecrement (&lock->guard.started);
+          /* Yield the CPU while waiting for another thread to finish
+             initializing this lock.  */
+          while (!lock->guard.done)
+            Sleep (0);
+        }
+    }
+  EnterCriticalSection (&lock->lock);
+  /* Test whether no readers or writers are currently running.  */
+  if (!(lock->runcount == 0))
+    {
+      /* This thread has to wait for a while.  Enqueue it among the
+         waiting_writers.  */
+      HANDLE event = glwthread_waitqueue_add (&lock->waiting_writers);
+      if (event != INVALID_HANDLE_VALUE)
+        {
+          DWORD result;
+          LeaveCriticalSection (&lock->lock);
+          /* Wait until another thread signals this event.  */
+          result = WaitForSingleObject (event, INFINITE);
+          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+            abort ();
+          CloseHandle (event);
+          /* The thread which signalled the event already did the bookkeeping:
+             removed us from the waiting_writers, set lock->runcount = -1.  */
+          if (!(lock->runcount == -1))
+            abort ();
+          return 0;
+        }
+      else
+        {
+          /* Allocation failure.  Weird.  */
+          do
+            {
+              LeaveCriticalSection (&lock->lock);
+              Sleep (1);
+              EnterCriticalSection (&lock->lock);
+            }
+          while (!(lock->runcount == 0));
+        }
+    }
+  lock->runcount--; /* runcount becomes -1 */
+  LeaveCriticalSection (&lock->lock);
+  return 0;
+}
+
+int
+glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock)
+{
+  if (!lock->guard.done)
+    {
+      if (InterlockedIncrement (&lock->guard.started) == 0)
+        /* This thread is the first one to need this lock.  Initialize it.  */
+        glwthread_rwlock_init (lock);
+      else
+        {
+          /* Don't let lock->guard.started grow and wrap around.  */
+          InterlockedDecrement (&lock->guard.started);
+          /* Yield the CPU while waiting for another thread to finish
+             initializing this lock.  */
+          while (!lock->guard.done)
+            Sleep (0);
+        }
+    }
+  /* It's OK to wait for this critical section, because it is never taken for a
+     long time.  */
+  EnterCriticalSection (&lock->lock);
+  /* Test whether only readers are currently running, and whether the runcount
+     field will not overflow, and whether no writer is waiting.  The latter
+     condition is because POSIX recommends that "write locks shall take
+     precedence over read locks", to avoid "writer starvation".  */
+  if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
+    {
+      /* This thread would have to wait for a while.  Return instead.  */
+      LeaveCriticalSection (&lock->lock);
+      return EBUSY;
+    }
+  lock->runcount++;
+  LeaveCriticalSection (&lock->lock);
+  return 0;
+}
+
+int
+glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock)
+{
+  if (!lock->guard.done)
+    {
+      if (InterlockedIncrement (&lock->guard.started) == 0)
+        /* This thread is the first one to need this lock.  Initialize it.  */
+        glwthread_rwlock_init (lock);
+      else
+        {
+          /* Don't let lock->guard.started grow and wrap around.  */
+          InterlockedDecrement (&lock->guard.started);
+          /* Yield the CPU while waiting for another thread to finish
+             initializing this lock.  */
+          while (!lock->guard.done)
+            Sleep (0);
+        }
+    }
+  /* It's OK to wait for this critical section, because it is never taken for a
+     long time.  */
+  EnterCriticalSection (&lock->lock);
+  /* Test whether no readers or writers are currently running.  */
+  if (!(lock->runcount == 0))
+    {
+      /* This thread would have to wait for a while.  Return instead.  */
+      LeaveCriticalSection (&lock->lock);
+      return EBUSY;
+    }
+  lock->runcount--; /* runcount becomes -1 */
+  LeaveCriticalSection (&lock->lock);
+  return 0;
+}
+
+int
+glwthread_rwlock_unlock (glwthread_rwlock_t *lock)
+{
+  if (!lock->guard.done)
+    return EINVAL;
+  EnterCriticalSection (&lock->lock);
+  if (lock->runcount < 0)
+    {
+      /* Drop a writer lock.  */
+      if (!(lock->runcount == -1))
+        abort ();
+      lock->runcount = 0;
+    }
+  else
+    {
+      /* Drop a reader lock.  */
+      if (!(lock->runcount > 0))
+        {
+          LeaveCriticalSection (&lock->lock);
+          return EPERM;
+        }
+      lock->runcount--;
+    }
+  if (lock->runcount == 0)
+    {
+      /* POSIX recommends that "write locks shall take precedence over read
+         locks", to avoid "writer starvation".  */
+      if (lock->waiting_writers.count > 0)
+        {
+          /* Wake up one of the waiting writers.  */
+          lock->runcount--;
+          glwthread_waitqueue_notify_first (&lock->waiting_writers);
+        }
+      else
+        {
+          /* Wake up all waiting readers.  */
+          lock->runcount += lock->waiting_readers.count;
+          glwthread_waitqueue_notify_all (&lock->waiting_readers);
+        }
+    }
+  LeaveCriticalSection (&lock->lock);
+  return 0;
+}
+
+int
+glwthread_rwlock_destroy (glwthread_rwlock_t *lock)
+{
+  if (!lock->guard.done)
+    return EINVAL;
+  if (lock->runcount != 0)
+    return EBUSY;
+  DeleteCriticalSection (&lock->lock);
+  if (lock->waiting_readers.array != NULL)
+    free (lock->waiting_readers.array);
+  if (lock->waiting_writers.array != NULL)
+    free (lock->waiting_writers.array);
+  lock->guard.done = 0;
+  return 0;
+}
diff --git a/gettext-runtime/intl/windows-rwlock.h b/gettext-runtime/intl/windows-rwlock.h
new file mode 100644 (file)
index 0000000..8fc017c
--- /dev/null
@@ -0,0 +1,68 @@
+/* Read-write locks (native Windows implementation).
+   Copyright (C) 2005-2019 Free Software Foundation, Inc.
+
+   This program 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.
+
+   This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+   Based on GCC's gthr-win32.h.  */
+
+#ifndef _WINDOWS_RWLOCK_H
+#define _WINDOWS_RWLOCK_H
+
+#define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+#include <windows.h>
+
+#include "windows-initguard.h"
+
+/* It is impossible to implement read-write locks using plain locks, without
+   introducing an extra thread dedicated to managing read-write locks.
+   Therefore here we need to use the low-level Event type.  */
+
+typedef struct
+        {
+          HANDLE *array; /* array of waiting threads, each represented by an event */
+          unsigned int count; /* number of waiting threads */
+          unsigned int alloc; /* length of allocated array */
+          unsigned int offset; /* index of first waiting thread in array */
+        }
+        glwthread_carray_waitqueue_t;
+typedef struct
+        {
+          glwthread_initguard_t guard; /* protects the initialization */
+          CRITICAL_SECTION lock; /* protects the remaining fields */
+          glwthread_carray_waitqueue_t waiting_readers; /* waiting readers */
+          glwthread_carray_waitqueue_t waiting_writers; /* waiting writers */
+          int runcount; /* number of readers running, or -1 when a writer runs */
+        }
+        glwthread_rwlock_t;
+
+#define GLWTHREAD_RWLOCK_INIT { GLWTHREAD_INITGUARD_INIT }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void glwthread_rwlock_init (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_rdlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_wrlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_unlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_destroy (glwthread_rwlock_t *lock);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WINDOWS_RWLOCK_H */
index 0433ac0f5919d57b585e3c61adf01f2f2db33efe..49ae00801d4969b0f2a6b0a2fb45d5fc004a66a6 100644 (file)
@@ -45,6 +45,7 @@
 
 /* #define DEBUG_THREADS */
 
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
 
 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \
@@ -79,6 +80,7 @@ static int libxml_is_threaded = 1;
 #endif /* __GNUC__, __GLIBC__, __linux__ */
 
 #endif /* HAVE_PTHREAD_H */
+#endif /* LIBXML_THREAD_ENABLED */
 
 /*
  * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
@@ -90,6 +92,7 @@ static int libxml_is_threaded = 1;
  * xmlMutex are a simple mutual exception locks
  */
 struct _xmlMutex {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_t lock;
 #elif defined HAVE_WIN32_THREADS
@@ -100,12 +103,16 @@ struct _xmlMutex {
 #else
     int empty;
 #endif
+#else
+    int empty;
+#endif
 };
 
 /*
  * xmlRMutex are reentrant mutual exception locks
  */
 struct _xmlRMutex {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_t lock;
     unsigned int held;
@@ -122,6 +129,9 @@ struct _xmlRMutex {
 #else
     int empty;
 #endif
+#else
+    int empty;
+#endif
 };
 
 /*
@@ -130,6 +140,7 @@ struct _xmlRMutex {
  *   - globalkey used for per-thread data
  */
 
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
 static pthread_key_t globalkey;
 static pthread_t mainthread;
@@ -158,6 +169,7 @@ int32 run_once_init = 0;
 static int32 global_init_lock = -1;
 static vint32 global_init_count = 0;
 #endif
+#endif
 
 static xmlRMutexPtr xmlLibraryLock = NULL;
 
@@ -180,6 +192,7 @@ xmlNewMutex(void)
 
     if ((tok = malloc(sizeof(xmlMutex))) == NULL)
         return (NULL);
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0)
         pthread_mutex_init(&tok->lock, NULL);
@@ -191,6 +204,7 @@ xmlNewMutex(void)
         return NULL;
     }
     tok->tid = -1;
+#endif
 #endif
     return (tok);
 }
@@ -208,6 +222,7 @@ xmlFreeMutex(xmlMutexPtr tok)
     if (tok == NULL)
         return;
 
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0)
         pthread_mutex_destroy(&tok->lock);
@@ -215,6 +230,7 @@ xmlFreeMutex(xmlMutexPtr tok)
     CloseHandle(tok->mutex);
 #elif defined HAVE_BEOS_THREADS
     delete_sem(tok->sem);
+#endif
 #endif
     free(tok);
 }
@@ -230,6 +246,7 @@ xmlMutexLock(xmlMutexPtr tok)
 {
     if (tok == NULL)
         return;
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0)
         pthread_mutex_lock(&tok->lock);
@@ -244,7 +261,7 @@ xmlMutexLock(xmlMutexPtr tok)
     }
     tok->tid = find_thread(NULL);
 #endif
-
+#endif
 }
 
 /**
@@ -258,6 +275,7 @@ xmlMutexUnlock(xmlMutexPtr tok)
 {
     if (tok == NULL)
         return;
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0)
         pthread_mutex_unlock(&tok->lock);
@@ -269,6 +287,7 @@ xmlMutexUnlock(xmlMutexPtr tok)
         release_sem(tok->sem);
     }
 #endif
+#endif
 }
 
 /**
@@ -288,6 +307,7 @@ xmlNewRMutex(void)
 
     if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
         return (NULL);
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0) {
         pthread_mutex_init(&tok->lock, NULL);
@@ -304,6 +324,7 @@ xmlNewRMutex(void)
         return NULL;
     }
     tok->count = 0;
+#endif
 #endif
     return (tok);
 }
@@ -320,6 +341,7 @@ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
 {
     if (tok == NULL)
         return;
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0) {
         pthread_mutex_destroy(&tok->lock);
@@ -329,6 +351,7 @@ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
     DeleteCriticalSection(&tok->cs);
 #elif defined HAVE_BEOS_THREADS
     xmlFreeMutex(tok->lock);
+#endif
 #endif
     free(tok);
 }
@@ -344,6 +367,7 @@ xmlRMutexLock(xmlRMutexPtr tok)
 {
     if (tok == NULL)
         return;
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded == 0)
         return;
@@ -376,6 +400,7 @@ xmlRMutexLock(xmlRMutexPtr tok)
         tok->count = 1;
     }
 #endif
+#endif
 }
 
 /**
@@ -389,6 +414,7 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
 {
     if (tok == NULL)
         return;
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded == 0)
         return;
@@ -415,6 +441,7 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
         return;
     }
 #endif
+#endif
 }
 
 /**
@@ -427,6 +454,7 @@ void
 __xmlGlobalInitMutexLock(void)
 {
     /* Make sure the global init lock is initialized and then lock it. */
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     /* The mutex is statically initialized, so we just lock it. */
 #ifdef XML_PTHREAD_WEAK
@@ -496,11 +524,13 @@ __xmlGlobalInitMutexLock(void)
 #endif
     }
 #endif
+#endif
 }
 
 void
 __xmlGlobalInitMutexUnlock(void)
 {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
 #ifdef XML_PTHREAD_WEAK
     if (pthread_mutex_unlock == NULL)
@@ -514,6 +544,7 @@ __xmlGlobalInitMutexUnlock(void)
 #elif defined HAVE_BEOS_THREADS
     release_sem(global_init_lock);
 #endif
+#endif
 }
 
 /**
@@ -525,6 +556,7 @@ __xmlGlobalInitMutexUnlock(void)
 void
 __xmlGlobalInitMutexDestroy(void)
 {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
 #elif defined HAVE_WIN32_THREADS
     if (global_init_lock != NULL) {
@@ -533,6 +565,7 @@ __xmlGlobalInitMutexDestroy(void)
         global_init_lock = NULL;
     }
 #endif
+#endif
 }
 
 /************************************************************************
@@ -590,6 +623,8 @@ xmlNewGlobalState(void)
 }
 #endif /* LIBXML_THREAD_ENABLED */
 
+#ifdef LIBXML_THREAD_ENABLED
+
 #ifdef HAVE_PTHREAD_H
 #elif defined HAVE_WIN32_THREADS
 #if !defined(HAVE_COMPILER_TLS)
@@ -643,6 +678,8 @@ xmlGlobalStateCleanup(void *data)
 }
 #endif
 
+#endif /* LIBXML_THREAD_ENABLED */
+
 /**
  * xmlGetGlobalState:
  *
@@ -653,6 +690,7 @@ xmlGlobalStateCleanup(void *data)
 xmlGlobalStatePtr
 xmlGetGlobalState(void)
 {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     xmlGlobalState *globalval;
 
@@ -743,6 +781,9 @@ xmlGetGlobalState(void)
 #else
     return (NULL);
 #endif
+#else
+    return (NULL);
+#endif
 }
 
 /************************************************************************
@@ -763,6 +804,7 @@ xmlGetGlobalState(void)
 int
 xmlGetThreadId(void)
 {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     pthread_t id;
     int ret;
@@ -780,6 +822,9 @@ xmlGetThreadId(void)
 #else
     return ((int) 0);
 #endif
+#else
+    return ((int) 0);
+#endif
 }
 
 /**
@@ -792,6 +837,7 @@ xmlGetThreadId(void)
 int
 xmlIsMainThread(void)
 {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded == -1)
         xmlInitThreads();
@@ -816,6 +862,9 @@ xmlIsMainThread(void)
 #else
     return (1);
 #endif
+#else
+    return (1);
+#endif
 }
 
 /**
@@ -857,6 +906,7 @@ xmlUnlockLibrary(void)
 void
 xmlInitThreads(void)
 {
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
 #ifdef XML_PTHREAD_WEAK
     if (libxml_is_threaded == -1) {
@@ -888,6 +938,7 @@ xmlInitThreads(void)
 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
     InitializeCriticalSection(&cleanup_helpers_cs);
 #endif
+#endif
 }
 
 /**
@@ -910,6 +961,7 @@ xmlCleanupThreads(void)
 #ifdef DEBUG_THREADS
     xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
 #endif
+#ifdef LIBXML_THREAD_ENABLED
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0)
         pthread_key_delete(globalkey);
@@ -934,6 +986,7 @@ xmlCleanupThreads(void)
     }
     DeleteCriticalSection(&cleanup_helpers_cs);
 #endif
+#endif
 }
 
 #ifdef LIBXML_THREAD_ENABLED