]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Make libintl multithread-safe.
authorBruno Haible <bruno@clisp.org>
Fri, 27 May 2005 10:40:37 +0000 (10:40 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:12:36 +0000 (12:12 +0200)
12 files changed:
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/bindtextdom.c
gettext-runtime/intl/dcigettext.c
gettext-runtime/intl/finddomain.c
gettext-runtime/intl/loadmsgcat.c
gettext-runtime/intl/localealias.c
gettext-runtime/intl/log.c
gettext-runtime/intl/textdomain.c
gettext-runtime/m4/ChangeLog
gettext-runtime/m4/gettext.m4
gettext-tools/tests/ChangeLog
gettext-tools/tests/Makefile.am

index 17ba1763432992c55e2fc6e7af24eace339c214b..9f3127546ad96b3c4ff980cfe6b2775d708b06fd 100644 (file)
@@ -1,3 +1,35 @@
+2005-05-05  Bruno Haible  <bruno@clisp.org>
+
+       Make libintl multithread-safe outside glibc.
+       * bindtextdom.c: Include THREAD_H.
+       (__libc_rwlock_*): Define also for USE_POSIX_THREADS or
+       USE_PTH_THREADS.
+       * dcigettext.c: Include THREAD_H.
+       (__libc_lock_*, __libc_rwlock_*): Define also for USE_POSIX_THREADS or
+       USE_PTH_THREADS.
+       (_nl_state_lock): Define always.
+       (tree_lock): Define outside DCIGETTEXT.
+       (DCIGETTEXT): ... not here.
+       * finddomain.c: Include THREAD_H.
+       (__libc_rwlock_*): Define also for USE_POSIX_THREADS or
+       USE_PTH_THREADS.
+       * loadmsgcat.c: Include THREAD_H.
+       (__libc_lock_*_recursive): Define also for USE_POSIX_THREADS or
+       USE_PTH_THREADS.
+       (_nl_load_domain): Remove extraneous comma.
+       * localealias.c: Include THREAD_H.
+       (__libc_lock_*): Define also for USE_POSIX_THREADS or USE_PTH_THREADS.
+       (lock): Define always.
+       (_nl_expand_alias): Use lock always.
+       * textdomain.c: Include THREAD_H.
+       (__libc_rwlock_*): Define also for USE_POSIX_THREADS or
+       USE_PTH_THREADS.
+       * log.c: Include THREAD_H.
+       (__libc_lock_*): Define also for USE_POSIX_THREADS or USE_PTH_THREADS.
+       (last_logfilename, last_logfile, lock): New variables.
+       (_nl_log_untranslated_locked): Renamed from _nl_log_untranslated.
+       (_nl_log_untranslated): Rewritten.
+
 2005-02-16  Roland McGrath  <roland@redhat.com>
 
        * dcigettext.c (_nl_find_msg): Add a cast.
index 95069804531ef07b86bd70f5989bdcbca5572077..4c34f617625b69dd787d4c41e59d19caf7432be8 100644 (file)
 #endif
 #include "gettextP.h"
 
+/* Handle multi-threaded applications.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
 #ifdef _LIBC
-/* We have to handle multi-threaded applications.  */
 # include <bits/libc-lock.h>
 #else
-/* Provide dummy implementation if this is outside glibc.  */
-# define __libc_rwlock_define(CLASS, NAME)
-# define __libc_rwlock_wrlock(NAME)
-# define __libc_rwlock_unlock(NAME)
+# if USE_POSIX_THREADS
+#  define __libc_rwlock_define(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME;
+#  define __libc_rwlock_define_initialized(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+#  define __libc_rwlock_rdlock(NAME)  \
+     if (pthread_rwlock_rdlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_wrlock(NAME)  \
+     if (pthread_rwlock_wrlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_unlock(NAME)  \
+     if (pthread_rwlock_unlock (&NAME) != 0) abort ()
+# else
+#  if USE_PTH_THREADS
+#   define __libc_rwlock_define(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME;
+#   define __libc_rwlock_define_initialized(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
+#   define __libc_rwlock_rdlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
+#   define __libc_rwlock_wrlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
+#   define __libc_rwlock_unlock(NAME) \
+      if (!pth_rwlock_release (&NAME)) abort ()
+#  else
+/* Provide dummy implementation if threads are not supported.  */
+#   define __libc_rwlock_define(CLASS, NAME)
+#   define __libc_rwlock_define_initialized(CLASS, NAME)
+#   define __libc_rwlock_rdlock(NAME)
+#   define __libc_rwlock_wrlock(NAME)
+#   define __libc_rwlock_unlock(NAME)
+#  endif
+# endif
 #endif
 
 /* The internal variables in the standalone libintl.a must have different
index c56ac3a10c50339d7a932184327957fd344ba236..5763cf38d7484dc4f2878b817e2d0826ec492776 100644 (file)
@@ -100,18 +100,65 @@ extern int errno;
 #endif
 #include "hash-string.h"
 
-/* Thread safetyness.  */
+/* Handle multi-threaded applications.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
 #ifdef _LIBC
 # include <bits/libc-lock.h>
 #else
-/* Provide dummy implementation if this is outside glibc.  */
-# define __libc_lock_define_initialized(CLASS, NAME)
-# define __libc_lock_lock(NAME)
-# define __libc_lock_unlock(NAME)
-# define __libc_rwlock_define_initialized(CLASS, NAME)
-# define __libc_rwlock_rdlock(NAME)
-# define __libc_rwlock_wrlock(NAME)
-# define __libc_rwlock_unlock(NAME)
+# if USE_POSIX_THREADS
+#  define __libc_lock_define(CLASS, NAME) \
+     CLASS pthread_mutex_t NAME;
+#  define __libc_lock_define_initialized(CLASS, NAME) \
+     CLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER;
+#  define __libc_lock_lock(NAME) \
+     if (pthread_mutex_lock (&NAME) != 0) abort ()
+#  define __libc_lock_unlock(NAME) \
+     if (pthread_mutex_unlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_define(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME;
+#  define __libc_rwlock_define_initialized(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+#  define __libc_rwlock_rdlock(NAME)  \
+     if (pthread_rwlock_rdlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_wrlock(NAME)  \
+     if (pthread_rwlock_wrlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_unlock(NAME)  \
+     if (pthread_rwlock_unlock (&NAME) != 0) abort ()
+# else
+#  if USE_PTH_THREADS
+#   define __libc_lock_define(CLASS, NAME) \
+      CLASS pth_mutex_t NAME;
+#   define __libc_lock_define_initialized(CLASS, NAME) \
+      CLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
+#   define __libc_lock_lock(NAME) \
+      if (!pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+#   define __libc_lock_unlock(NAME) \
+      if (!pth_mutex_release (&NAME)) abort ()
+#   define __libc_rwlock_define(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME;
+#   define __libc_rwlock_define_initialized(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
+#   define __libc_rwlock_rdlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
+#   define __libc_rwlock_wrlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
+#   define __libc_rwlock_unlock(NAME) \
+      if (!pth_rwlock_release (&NAME)) abort ()
+#  else
+/* Provide dummy implementation if threads are not supported.  */
+#   define __libc_lock_define(CLASS, NAME)
+#   define __libc_lock_define_initialized(CLASS, NAME)
+#   define __libc_lock_lock(NAME)
+#   define __libc_lock_unlock(NAME)
+#   define __libc_rwlock_define(CLASS, NAME)
+#   define __libc_rwlock_define_initialized(CLASS, NAME)
+#   define __libc_rwlock_rdlock(NAME)
+#   define __libc_rwlock_wrlock(NAME)
+#   define __libc_rwlock_unlock(NAME)
+#  endif
+# endif
 #endif
 
 /* Alignment of types.  */
@@ -260,6 +307,8 @@ struct known_translation_t
 #if defined HAVE_TSEARCH || defined _LIBC
 # include <search.h>
 
+__libc_rwlock_define_initialized (static, tree_lock);
+
 static void *root;
 
 # ifdef _LIBC
@@ -407,9 +456,7 @@ typedef unsigned char transmem_block_t;
 #endif
 
 /* Lock variable to protect the global data in the gettext implementation.  */
-#ifdef _LIBC
 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
-#endif
 
 /* Checking whether the binaries runs SUID must be done and glibc provides
    easier methods therefore we make a difference here.  */
@@ -536,7 +583,6 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
 
   /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
      tsearch calls can be fatal.  */
-  __libc_rwlock_define_initialized (static, tree_lock);
   __libc_rwlock_rdlock (tree_lock);
 
   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
index 8523ea8bf4761349d9a1255df4b02ccd1eff45e9..a7a024dcfbf132fc844651d68f13b3d2f0474d7b 100644 (file)
 # include "libgnuintl.h"
 #endif
 
+/* Handle multi-threaded applications.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
 #ifdef _LIBC
 # include <bits/libc-lock.h>
 #else
-# define __libc_rwlock_define_initialized(CLASS, NAME)
-# define __libc_rwlock_rdlock(NAME)
-# define __libc_rwlock_wrlock(NAME)
-# define __libc_rwlock_unlock(NAME)
+# if USE_POSIX_THREADS
+#  define __libc_rwlock_define(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME;
+#  define __libc_rwlock_define_initialized(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+#  define __libc_rwlock_rdlock(NAME)  \
+     if (pthread_rwlock_rdlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_wrlock(NAME)  \
+     if (pthread_rwlock_wrlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_unlock(NAME)  \
+     if (pthread_rwlock_unlock (&NAME) != 0) abort ()
+# else
+#  if USE_PTH_THREADS
+#   define __libc_rwlock_define(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME;
+#   define __libc_rwlock_define_initialized(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
+#   define __libc_rwlock_rdlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
+#   define __libc_rwlock_wrlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
+#   define __libc_rwlock_unlock(NAME) \
+      if (!pth_rwlock_release (&NAME)) abort ()
+#  else
+/* Provide dummy implementation if threads are not supported.  */
+#   define __libc_rwlock_define(CLASS, NAME)
+#   define __libc_rwlock_define_initialized(CLASS, NAME)
+#   define __libc_rwlock_rdlock(NAME)
+#   define __libc_rwlock_wrlock(NAME)
+#   define __libc_rwlock_unlock(NAME)
+#  endif
+# endif
 #endif
 
 /* @@ end of prolog @@ */
index 26d0b87b15d92e159e1258cedfe351ff145415e3..babed6365001a1acc78d295f8e216e52d8f8f0b8 100644 (file)
@@ -92,11 +92,67 @@ char *alloca ();
 #ifdef _LIBC
 # include "../locale/localeinfo.h"
 # include <not-cancel.h>
+#endif
+
+/* Handle multi-threaded applications.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
+#ifdef _LIBC
 # include <bits/libc-lock.h>
 #else
-# define __libc_lock_define_initialized_recursive(CLASS, NAME)
-# define __libc_lock_lock_recursive(NAME)
-# define __libc_lock_unlock_recursive(NAME)
+# if USE_POSIX_THREADS
+#  define __libc_lock_define_recursive(CLASS, NAME) \
+     CLASS pthread_mutex_t NAME;
+#  define __libc_lock_define_initialized_recursive(CLASS, NAME) \
+     CLASS pthread_mutex_t NAME;                                             \
+     static pthread_mutex_t NAME##_aux = PTHREAD_MUTEX_INITIALIZER;          \
+     static int NAME##_initialized = 0;                                              \
+     auto int NAME##_dummy =                                                 \
+       ((NAME##_initialized == 0                                             \
+         ? mutex_init_recursive (&NAME, &NAME##_aux), NAME##_initialized = 1, 0 \
+         : 0), NAME##_dummy);
+static inline void
+mutex_init_recursive (pthread_mutex_t *mutex, pthread_mutex_t *mutex_aux)
+{
+  pthread_mutexattr_t attributes;
+
+  if (pthread_mutex_lock (mutex_aux) != 0)
+    abort ();
+  if (pthread_mutexattr_init (&attributes) != 0)
+    abort ();
+  if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0)
+    abort ();
+  if (pthread_mutex_init (mutex, &attributes) != 0)
+    abort ();
+  if (pthread_mutexattr_destroy (&attributes) != 0)
+    abort ();
+  if (pthread_mutex_unlock (mutex_aux) != 0)
+    abort ();
+}
+#  define __libc_lock_lock_recursive(NAME) \
+     if (pthread_mutex_lock (&NAME) != 0) abort ()
+#  define __libc_lock_unlock_recursive(NAME) \
+     if (pthread_mutex_unlock (&NAME) != 0) abort ()
+# else
+#  if USE_PTH_THREADS
+    /* In Pth, mutexes are recursive by default.  */
+#   define __libc_lock_define_recursive(CLASS, NAME) \
+      CLASS pth_mutex_t NAME;
+#   define __libc_lock_define_initialized_recursive(CLASS, NAME) \
+      CLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
+#   define __libc_lock_lock_recursive(NAME) \
+      if (!pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+#   define __libc_lock_unlock_recursive(NAME) \
+      if (!pth_mutex_release (&NAME)) abort ()
+#  else
+/* Provide dummy implementation if threads are not supported.  */
+#   define __libc_lock_define_recursive(CLASS, NAME)
+#   define __libc_lock_define_initialized_recursive(CLASS, NAME)
+#   define __libc_lock_lock_recursive(NAME)
+#   define __libc_lock_unlock_recursive(NAME)
+#  endif
+# endif
 #endif
 
 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
@@ -778,7 +834,7 @@ internal_function
 _nl_load_domain (struct loaded_l10nfile *domain_file,
                 struct binding *domainbinding)
 {
-  __libc_lock_define_initialized_recursive (static, lock);
+  __libc_lock_define_initialized_recursive (static, lock)
   int fd = -1;
   size_t size;
 #ifdef _LIBC
index de7fca496f60de6ce9eef406861ab8eb93bc70d2..6dfcc8bd8626be78e38ee07032d0cec3aa8c371c 100644 (file)
@@ -81,11 +81,43 @@ char *alloca ();
 # endif
 # define HAVE_MEMPCPY  1
 # define HAVE___FSETLOCKING    1
+#endif
 
-/* We need locking here since we can be called from different places.  */
+/* Handle multi-threaded applications.
+   We need locking here since we can be called from different places.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
+#ifdef _LIBC
 # include <bits/libc-lock.h>
-
-__libc_lock_define_initialized (static, lock);
+#else
+# if USE_POSIX_THREADS
+#  define __libc_lock_define(CLASS, NAME) \
+     CLASS pthread_mutex_t NAME;
+#  define __libc_lock_define_initialized(CLASS, NAME) \
+     CLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER;
+#  define __libc_lock_lock(NAME) \
+     if (pthread_mutex_lock (&NAME) != 0) abort ()
+#  define __libc_lock_unlock(NAME) \
+     if (pthread_mutex_unlock (&NAME) != 0) abort ()
+# else
+#  if USE_PTH_THREADS
+#   define __libc_lock_define(CLASS, NAME) \
+      CLASS pth_mutex_t NAME;
+#   define __libc_lock_define_initialized(CLASS, NAME) \
+      CLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
+#   define __libc_lock_lock(NAME) \
+      if (!pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+#   define __libc_lock_unlock(NAME) \
+      if (!pth_mutex_release (&NAME)) abort ()
+#  else
+/* Provide dummy implementation if threads are not supported.  */
+#   define __libc_lock_define(CLASS, NAME)
+#   define __libc_lock_define_initialized(CLASS, NAME)
+#   define __libc_lock_lock(NAME)
+#   define __libc_lock_unlock(NAME)
+#  endif
+# endif
 #endif
 
 #ifndef internal_function
@@ -120,6 +152,9 @@ __libc_lock_define_initialized (static, lock);
 #endif
 
 
+__libc_lock_define_initialized (static, lock)
+
+
 struct alias_map
 {
   const char *alias;
@@ -155,9 +190,7 @@ _nl_expand_alias (const char *name)
   const char *result = NULL;
   size_t added;
 
-#ifdef _LIBC
   __libc_lock_lock (lock);
-#endif
 
   if (locale_alias_path == NULL)
     locale_alias_path = LOCALE_ALIAS_PATH;
@@ -204,9 +237,7 @@ _nl_expand_alias (const char *name)
     }
   while (added != 0);
 
-#ifdef _LIBC
   __libc_lock_unlock (lock);
-#endif
 
   return result;
 }
index 89f82dfd141df866633e47d2773ef460c4c6d871..92b4daba409530a11913da01cd6364b140f4a4a9 100644 (file)
@@ -1,5 +1,5 @@
 /* Log file output.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published
 #include <stdlib.h>
 #include <string.h>
 
+/* Handle multi-threaded applications.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
+#if USE_POSIX_THREADS
+# define __libc_lock_define(CLASS, NAME) \
+    CLASS pthread_mutex_t NAME;
+# define __libc_lock_define_initialized(CLASS, NAME) \
+    CLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER;
+# define __libc_lock_lock(NAME) \
+    if (pthread_mutex_lock (&NAME) != 0) abort ()
+# define __libc_lock_unlock(NAME) \
+    if (pthread_mutex_unlock (&NAME) != 0) abort ()
+#else
+# if USE_PTH_THREADS
+#  define __libc_lock_define(CLASS, NAME) \
+     CLASS pth_mutex_t NAME;
+#  define __libc_lock_define_initialized(CLASS, NAME) \
+     CLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
+#  define __libc_lock_lock(NAME) \
+     if (!pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+#  define __libc_lock_unlock(NAME) \
+     if (!pth_mutex_release (&NAME)) abort ()
+# else
+/* Provide dummy implementation if threads are not supported.  */
+#  define __libc_lock_define(CLASS, NAME)
+#  define __libc_lock_define_initialized(CLASS, NAME)
+#  define __libc_lock_lock(NAME)
+#  define __libc_lock_unlock(NAME)
+# endif
+#endif
+
 /* Print an ASCII string with quotes and escape sequences where needed.  */
 static void
 print_escaped (FILE *stream, const char *str)
@@ -48,13 +80,14 @@ print_escaped (FILE *stream, const char *str)
   putc ('"', stream);
 }
 
-/* Add to the log file an entry denoting a failed translation.  */
-void
-_nl_log_untranslated (const char *logfilename, const char *domainname,
-                     const char *msgid1, const char *msgid2, int plural)
+static char *last_logfilename = NULL;
+static FILE *last_logfile = NULL;
+__libc_lock_define_initialized (static, lock)
+
+static inline void
+_nl_log_untranslated_locked (const char *logfilename, const char *domainname,
+                            const char *msgid1, const char *msgid2, int plural)
 {
-  static char *last_logfilename = NULL;
-  static FILE *last_logfile = NULL;
   FILE *logfile;
 
   /* Can we reuse the last opened logfile?  */
@@ -96,3 +129,13 @@ _nl_log_untranslated (const char *logfilename, const char *domainname,
     fprintf (logfile, "\nmsgstr \"\"\n");
   putc ('\n', logfile);
 }
+
+/* Add to the log file an entry denoting a failed translation.  */
+void
+_nl_log_untranslated (const char *logfilename, const char *domainname,
+                     const char *msgid1, const char *msgid2, int plural)
+{
+  __libc_lock_lock (lock);
+  _nl_log_untranslated_locked (logfilename, domainname, msgid1, msgid2, plural);
+  __libc_lock_unlock (lock);
+}
index 2bf62407dba9054853f8835a348c4074276244ed..d484df585e93a213a2fdfc510981cf765cd82895 100644 (file)
@@ -1,5 +1,5 @@
 /* Implementation of the textdomain(3) function.
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2003, 2005 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published
 #endif
 #include "gettextP.h"
 
+/* Handle multi-threaded applications.  */
+#ifdef THREAD_H
+# include THREAD_H
+#endif
 #ifdef _LIBC
-/* We have to handle multi-threaded applications.  */
 # include <bits/libc-lock.h>
 #else
-/* Provide dummy implementation if this is outside glibc.  */
-# define __libc_rwlock_define(CLASS, NAME)
-# define __libc_rwlock_wrlock(NAME)
-# define __libc_rwlock_unlock(NAME)
+# if USE_POSIX_THREADS
+#  define __libc_rwlock_define(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME;
+#  define __libc_rwlock_define_initialized(CLASS, NAME) \
+     CLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+#  define __libc_rwlock_rdlock(NAME)  \
+     if (pthread_rwlock_rdlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_wrlock(NAME)  \
+     if (pthread_rwlock_wrlock (&NAME) != 0) abort ()
+#  define __libc_rwlock_unlock(NAME)  \
+     if (pthread_rwlock_unlock (&NAME) != 0) abort ()
+# else
+#  if USE_PTH_THREADS
+#   define __libc_rwlock_define(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME;
+#   define __libc_rwlock_define_initialized(CLASS, NAME) \
+      CLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
+#   define __libc_rwlock_rdlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
+#   define __libc_rwlock_wrlock(NAME) \
+      if (!pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
+#   define __libc_rwlock_unlock(NAME) \
+      if (!pth_rwlock_release (&NAME)) abort ()
+#  else
+/* Provide dummy implementation if threads are not supported.  */
+#   define __libc_rwlock_define(CLASS, NAME)
+#   define __libc_rwlock_define_initialized(CLASS, NAME)
+#   define __libc_rwlock_rdlock(NAME)
+#   define __libc_rwlock_wrlock(NAME)
+#   define __libc_rwlock_unlock(NAME)
+#  endif
+# endif
 #endif
 
 /* The internal variables in the standalone libintl.a must have different
index ed5eca42c3db5f585f672d10541f71c9f24a0d9d..ad7638ca7eefe98099c8342535c31b2cbfcc3420 100644 (file)
@@ -1,3 +1,9 @@
+2005-05-05  Bruno Haible  <bruno@clisp.org>
+
+       * gettext.m4 (AM_GNU_GETTEXT): Add LIBTHREAD to LIBINTL and
+       LTLIBTHREAD to LTLIBINTL.
+       (AM_INTL_SUBDIR): Check for thread library. Set LIBTHREAD, LTLIBTHREAD.
+
 2005-03-13  Bruno Haible  <bruno@clisp.org>
 
        * po.m4 (AM_PO_SUBDIRS): Use AC_CONFIG_COMMANDS instead of
index dc6274338744b911c67aa1431bf6e96f45813eef..e42a8e32779f476733bcb5fa0090a882801ce2b8 100644 (file)
@@ -1,4 +1,4 @@
-# gettext.m4 serial 39 (gettext-0.15)
+# gettext.m4 serial 40 (gettext-0.15)
 dnl Copyright (C) 1995-2005 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -234,8 +234,8 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)],
         dnl Mark actions used to generate GNU NLS library.
         BUILD_INCLUDED_LIBINTL=yes
         USE_INCLUDED_LIBINTL=yes
-        LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV"
-        LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV"
+        LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD"
+        LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD"
         LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
       fi
 
@@ -444,7 +444,7 @@ __fsetlocking])
     gt_LC_MESSAGES
   fi
 
-  dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOUURCE is defined,
+  dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined,
   dnl and a _NL_LOCALE_NAME macro always.
   AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name,
     [AC_TRY_LINK([#include <langinfo.h>],
@@ -454,9 +454,68 @@ __fsetlocking])
     ])
   if test $gt_cv_nl_locale_name = yes; then
     AC_DEFINE(HAVE_NL_LOCALE_NAME, 1,
-      [Define if you have <langinfo.h> and it defines the NL_LOCALE_NAME macro if _GNU_SOUURCE is defined.])
+      [Define if you have <langinfo.h> and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.])
   fi
 
+  dnl Check for multithreading.
+  AC_ARG_ENABLE(threads,
+    AC_HELP_STRING([--disable-threads], [build without multithread safety]),
+    gt_use_threads=$enableval, gt_use_threads=yes)
+  LIBTHREAD=
+  LTLIBTHREAD=
+  if test "$gt_use_threads" != no; then
+    THREAD_H=
+    if test "$gt_use_threads" = yes || test "$gt_use_threads" = posix; then
+      AC_CHECK_HEADER(pthread.h, gt_have_pthread_h=yes, gt_have_pthread_h=no)
+      if test "$gt_have_pthread_h" = yes; then
+        # Other possible tests:
+        #   compiler flag -pthread
+        #   -lc_r (AIX, FreeBSD)
+        #   -lpthreads (FSU threads, PCthreads)
+        #   -lthread
+        #   -lgthreads
+        gt_have_pthread=
+        if test -z "$gt_have_pthread"; then
+          AC_CHECK_LIB(pthread, pthread_self,
+            [gt_have_pthread=yes LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread])
+        fi
+        if test -n "$gt_have_pthread"; then
+          THREAD_H='<pthread.h>'
+          CPPFLAGS="$CPPFLAGS -DUSE_POSIX_THREADS"
+          case "$host_os" in
+            # aix*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
+            # freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
+            # linux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
+            solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
+          esac
+        fi
+      fi
+    fi
+    if test "$gt_use_threads" = pth; then
+      gt_save_CPPFLAGS="$CPPFLAGS"
+      AC_LIB_LINKFLAGS(pth)
+      gt_have_pth=
+      gt_save_LIBS="$LIBS"
+      LIBS="$LIBS -lpth"
+      AC_TRY_LINK([#include <pth.h>], [pth_self();], gt_have_pth=yes)
+      LIBS="$gt_save_LIBS"
+      if test -n "$gt_have_pth"; then
+        LIBTHREAD="$LIBPTH"
+        LTLIBTHREAD="$LTLIBPTH"
+        THREAD_H='<pth.h>'
+        CPPFLAGS="$CPPFLAGS -DUSE_PTH_THREADS"
+      else
+        CPPFLAGS="$gt_save_CPPFLAGS"
+      fi
+    fi
+    if test -n "$THREAD_H"; then
+      AC_DEFINE_UNQUOTED(THREAD_H, [$THREAD_H],
+        [Define to the header that declares multithreading facilities.])
+    fi
+  fi
+  AC_SUBST(LIBTHREAD)
+  AC_SUBST(LTLIBTHREAD)
+
   dnl intl/plural.c is generated from intl/plural.y. It requires bison,
   dnl because plural.y uses bison specific features. It requires at least
   dnl bison-1.26 because earlier versions generate a plural.c that doesn't
index cb2e9a2d98ec1690186d57094a274449ee4cd570..657305ae8974231034353cc164a1db6ebda9e576 100644 (file)
@@ -1,3 +1,7 @@
+2005-05-05  Bruno Haible  <bruno@clisp.org>
+
+       * Makefile.am (LDADD_yes, LDADD_no): Add @LTLIBTHREAD@.
+
 2005-05-01  Bruno Haible  <bruno@clisp.org>
 
        * xgettext-sh-4: New file.
index bd059f2ff90c4cd789a14c62efa659938abd8b96..b1fee6a9a12b745842eb0dcbfdd713e3927c7d10 100644 (file)
@@ -171,8 +171,8 @@ DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
 # INTL_MACOSX_LIBS is needed because the programs depend on libintl.la
 # but libtool doesn't put -Wl,-framework options into .la files.
 LDADD = $(LDADD_@USE_INCLUDED_LIBINTL@) @INTL_MACOSX_LIBS@
-LDADD_yes = ../intl/libintl.la
-LDADD_no = ../intl/libgnuintl.la @LTLIBINTL@
+LDADD_yes = ../intl/libintl.la @LTLIBTHREAD@
+LDADD_no = ../intl/libgnuintl.la @LTLIBTHREAD@ @LTLIBINTL@
 noinst_PROGRAMS = tstgettext tstngettext testlocale gettext-3-prg gettext-4-prg gettext-5-prg gettext-6-prg gettext-7-prg cake fc3 fc4 fc5
 tstgettext_SOURCES = tstgettext.c setlocale.c
 tstgettext_CFLAGS = -DINSTALLDIR=\".\"