changeset 39938:1ebb12ec25e0

localename: Fine-tune support for per-thread locales on Solaris 11.4. * lib/localename-table.h: New file, extracted from lib/localename.c. * lib/localename-table.c: Likewise. * lib/localename.c: Include localename-table.h. (get_locale_t_name, newlocale, duplocale, freelocale): Invoke locale_hash_function instead of pointer_hash. * modules/localename (Files): Add lib/localename-table.h, lib/localename-table.c. (lib_SOURCES): Add localename-table.c. * m4/intlsolaris.m4 (gt_INTL_SOLARIS): Require AC_CANONICAL_HOST. Test for Solaris 11.4 locale system only on Solaris. Test for it independently whether getlocalename_l exists. * m4/intl.m4 (gt_INTL_SUBDIR_CORE): Don't test for 'uselocale' and 'getlocalename_l'. Instead, invoke gt_INTL_SOLARIS. Set HAVE_NAMELESS_LOCALES. * modules/gettext (Files): Add m4/intlsolaris.m4.
author Bruno Haible <bruno@clisp.org>
date Mon, 22 Oct 2018 02:38:39 +0200
parents 33d4c96d8486
children 731ade0f3b50
files ChangeLog lib/localename-table.c lib/localename-table.h lib/localename.c m4/intlsolaris.m4 modules/gettext modules/localename
diffstat 7 files changed, 190 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Oct 22 02:34:07 2018 +0200
+++ b/ChangeLog	Mon Oct 22 02:38:39 2018 +0200
@@ -1,3 +1,22 @@
+2018-10-21  Bruno Haible  <bruno@clisp.org>
+
+	localename: Fine-tune support for per-thread locales on Solaris 11.4.
+	* lib/localename-table.h: New file, extracted from lib/localename.c.
+	* lib/localename-table.c: Likewise.
+	* lib/localename.c: Include localename-table.h.
+	(get_locale_t_name, newlocale, duplocale, freelocale): Invoke
+	locale_hash_function instead of pointer_hash.
+	* modules/localename (Files): Add lib/localename-table.h,
+	lib/localename-table.c.
+	(lib_SOURCES): Add localename-table.c.
+	* m4/intlsolaris.m4 (gt_INTL_SOLARIS): Require AC_CANONICAL_HOST. Test
+	for Solaris 11.4 locale system only on Solaris. Test for it
+	independently whether getlocalename_l exists.
+	* m4/intl.m4 (gt_INTL_SUBDIR_CORE): Don't test for 'uselocale' and
+	'getlocalename_l'. Instead, invoke gt_INTL_SOLARIS. Set
+	HAVE_NAMELESS_LOCALES.
+	* modules/gettext (Files): Add m4/intlsolaris.m4.
+
 2018-10-21  Bruno Haible  <bruno@clisp.org>
 
 	Small update from gettext.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/localename-table.c	Mon Oct 22 02:38:39 2018 +0200
@@ -0,0 +1,48 @@
+/* Table that maps a locale object to the names of the locale categories.
+   Copyright (C) 2018 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>, 2018.  */
+
+#include <config.h>
+
+#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */
+
+/* Specification.  */
+#include "localename-table.h"
+
+#include <stdint.h>
+
+/* A hash function for pointers.  */
+size_t _GL_ATTRIBUTE_CONST
+locale_hash_function (locale_t x)
+{
+  uintptr_t p = (uintptr_t) x;
+  size_t h = ((p % 4177) << 12) + ((p % 79) << 6) + (p % 61);
+  return h;
+}
+
+struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE]
+  /* = { NULL, ..., NULL } */;
+
+gl_rwlock_define_initialized(, locale_lock)
+
+#else
+
+/* This declaration is solely to ensure that after preprocessing
+   this file is never empty.  */
+typedef int dummy;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/localename-table.h	Mon Oct 22 02:38:39 2018 +0200
@@ -0,0 +1,73 @@
+/* Table that maps a locale object to the names of the locale categories.
+   Copyright (C) 2018 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>, 2018.  */
+
+#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */
+
+# include <stddef.h>
+# include <locale.h>
+
+# ifdef IN_LIBINTL
+#  include "lock.h"
+# else
+#  include "glthread/lock.h"
+# endif
+
+struct locale_categories_names
+  {
+    /* Locale category -> name (allocated with indefinite extent).  */
+    const char *category_name[6];
+  };
+
+/* A hash table of fixed size.  Multiple threads can access it read-only
+   simultaneously, but only one thread can insert into it or remove from it
+   at the same time.
+   This hash table has global scope, so that when an application uses both
+   GNU libintl and gnulib, the application sees only one hash table.  (When
+   linking statically with libintl, the fact that localename-table.c is a
+   separate compilation unit resolves the duplicate symbol conflict.  When
+   linking with libintl as a shared library, we rely on ELF and the symbol
+   conflict resolution implemented in the ELF dynamic loader here.)
+   Both the libintl overrides and the gnulib overrides of the functions
+   newlocale, duplocale, freelocale see the same hash table (and the same lock).
+   For this reason, the internal layout of the hash table and the hash function
+   MUST NEVER CHANGE.  If you need to change the internal layout or the hash
+   function, introduce versioning by appending a version suffix to the symbols
+   at the linker level.  */
+# define locale_hash_function libintl_locale_hash_function
+# define locale_hash_table libintl_locale_hash_table
+# define locale_lock libintl_locale_lock
+
+extern size_t _GL_ATTRIBUTE_CONST locale_hash_function (locale_t x);
+
+/* A node in a hash bucket collision list.  */
+struct locale_hash_node
+  {
+    struct locale_hash_node *next;
+    locale_t locale;
+    struct locale_categories_names names;
+  };
+
+# define LOCALE_HASH_TABLE_SIZE 101
+extern struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE];
+
+/* This lock protects the locale_hash_table against multiple simultaneous
+   accesses (except that multiple simultaneous read accesses are allowed).  */
+
+gl_rwlock_define(extern, locale_lock)
+
+#endif
--- a/lib/localename.c	Mon Oct 22 02:34:07 2018 +0200
+++ b/lib/localename.c	Mon Oct 22 02:38:39 2018 +0200
@@ -52,7 +52,7 @@
 # endif
 # if HAVE_NAMELESS_LOCALES
 #  include <errno.h>
-#  include <stdint.h>
+#  include "localename-table.h"
 # endif
 #endif
 
@@ -2707,43 +2707,8 @@
 #if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */
 
 /* The 'locale_t' object does not contain the names of the locale categories.
-   We have to associate them with the object through a hash table.  */
-
-struct locale_categories_names
-  {
-    /* Locale category -> name (allocated with indefinite extent).  */
-    const char *category_name[6];
-  };
-
-/* A hash function for pointers.  */
-static size_t _GL_ATTRIBUTE_CONST
-pointer_hash (const void *x)
-{
-  uintptr_t p = (uintptr_t) x;
-  size_t h = ((p % 4177) << 12) + ((p % 79) << 6) + (p % 61);
-  return h;
-}
-
-/* A hash table of fixed size.  Multiple threads can access it read-only
-   simultaneously, but only one thread can insert into it or remove from it
-   at the same time.  */
-
-/* A node in a hash bucket collision list.  */
-struct locale_hash_node
-  {
-    struct locale_hash_node *next;
-    locale_t locale;
-    struct locale_categories_names names;
-  };
-
-# define LOCALE_HASH_TABLE_SIZE 101
-static struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE]
-  /* = { NULL, ..., NULL } */;
-
-/* This lock protects the locale_hash_table against multiple simultaneous
-   accesses (except that multiple simultaneous read accesses are allowed).  */
-
-gl_rwlock_define_initialized(static, locale_lock)
+   We have to associate them with the object through a hash table.
+   The hash table is defined in localename-table.[hc].  */
 
 /* Returns the name of a given locale category in a given locale_t object,
    allocated as a string with indefinite extent.  */
@@ -2763,7 +2728,7 @@
   else
     {
       /* Look up the names in the hash table.  */
-      size_t hashcode = pointer_hash (locale);
+      size_t hashcode = locale_hash_function (locale);
       size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
       /* If the locale was not found in the table, return "".  This can
          happen if the application uses the original newlocale()/duplocale()
@@ -2898,7 +2863,7 @@
 
           /* Lock while looking up the hash node.  */
           gl_rwlock_rdlock (locale_lock);
-          for (p = locale_hash_table[pointer_hash (base) % LOCALE_HASH_TABLE_SIZE];
+          for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE];
                p != NULL;
                p = p->next)
             if (p->locale == base)
@@ -2961,7 +2926,7 @@
 
   /* Insert it in the hash table.  */
   {
-    size_t hashcode = pointer_hash (result);
+    size_t hashcode = locale_hash_function (result);
     size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
     struct locale_hash_node *p;
 
@@ -3036,7 +3001,7 @@
       /* Lock once, for the lookup and the insertion.  */
       gl_rwlock_wrlock (locale_lock);
 
-      for (p = locale_hash_table[pointer_hash (locale) % LOCALE_HASH_TABLE_SIZE];
+      for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE];
            p != NULL;
            p = p->next)
         if (p->locale == locale)
@@ -3057,7 +3022,7 @@
 
   /* Insert it in the hash table.  */
   {
-    size_t hashcode = pointer_hash (result);
+    size_t hashcode = locale_hash_function (result);
     size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
     struct locale_hash_node *p;
 
@@ -3094,7 +3059,7 @@
     abort ();
 
   {
-    size_t hashcode = pointer_hash (locale);
+    size_t hashcode = locale_hash_function (locale);
     size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
     struct locale_hash_node *found;
     struct locale_hash_node **p;
--- a/m4/intlsolaris.m4	Mon Oct 22 02:34:07 2018 +0200
+++ b/m4/intlsolaris.m4	Mon Oct 22 02:38:39 2018 +0200
@@ -1,4 +1,4 @@
-# intlsolaris.m4 serial 1
+# intlsolaris.m4 serial 2
 dnl Copyright (C) 2015-2018 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -17,37 +17,49 @@
 dnl Sets gt_nameless_locales.
 AC_DEFUN([gt_INTL_SOLARIS],
 [
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
   dnl Persuade Solaris <locale.h> to define 'locale_t'.
   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
   AC_CHECK_FUNCS_ONCE([uselocale])
 
   gt_nameless_locales=no
-  dnl Solaris 12 provides getlocalename_l, while Illumos doesn't have
-  dnl it nor the equivalent.
+  if test $ac_cv_func_uselocale = yes; then
+    AC_CACHE_CHECK([for Solaris 11.4 locale system],
+      [gt_cv_locale_solaris114],
+      [case "$host_os" in
+         solaris*)
+           dnl Test whether <locale.h> defines locale_t as a typedef of
+           dnl 'struct _LC_locale_t **' (whereas Illumos defines it as a
+           dnl typedef of 'struct _locale *').
+           AC_COMPILE_IFELSE(
+             [AC_LANG_PROGRAM([[
+                #include <locale.h>
+                struct _LC_locale_t *x;
+                locale_t y;
+              ]],
+              [[*y = x;]])],
+             [gt_cv_locale_solaris114=yes],
+             [gt_cv_locale_solaris114=no])
+           ;;
+         *) gt_cv_locale_solaris114=no ;;
+       esac
+      ])
+  fi
+  if test $gt_cv_locale_solaris114 = yes; then
+    gt_nameless_locales=yes
+    AC_DEFINE([HAVE_NAMELESS_LOCALES], [1],
+      [Define if the locale_t type does not contain the name of each locale category.])
+  fi
+
+  dnl Solaris 12 will maybe provide getlocalename_l.  If it does, it will
+  dnl simplify the implementation of gl_locale_name_thread().  But the overrides
+  dnl of newlocale, duplocale, freelocale will still be necessary, in order to
+  dnl keep the libintl_locale_hash_table up-to-date, which may be used by
+  dnl libintl or gnulib code that was compiled on Solaris 11.4, before
+  dnl getlocalename_l was introduced.
   if test $ac_cv_func_uselocale = yes; then
     AC_CHECK_FUNCS([getlocalename_l])
-    if test $ac_cv_func_getlocalename_l != yes; then
-      AC_CACHE_CHECK([for Solaris 11.4 locale system],
-        [gt_cv_locale_solaris114],
-        [dnl Test whether <locale.h> defines locale_t as a typedef of
-         dnl 'struct _LC_locale_t **' (whereas Illumos defines it as a
-         dnl typedef of 'struct _locale *').
-         AC_COMPILE_IFELSE(
-           [AC_LANG_PROGRAM([[
-              #include <locale.h>
-              struct _LC_locale_t *x;
-              locale_t y;
-            ]],
-            [[*y = x;]])],
-           [gt_cv_locale_solaris114=yes],
-           [gt_cv_locale_solaris114=no])
-        ])
-      if test $gt_cv_locale_solaris114 = yes; then
-        gt_nameless_locales=yes
-        AC_DEFINE([HAVE_NAMELESS_LOCALES], [1],
-          [Define if the locale_t type does not contain the name of each locale category.])
-      fi
-    fi
   fi
 ])
--- a/modules/gettext	Mon Oct 22 02:34:07 2018 +0200
+++ b/modules/gettext	Mon Oct 22 02:38:39 2018 +0200
@@ -20,6 +20,7 @@
 m4/intl.m4
 m4/intldir.m4
 m4/intlmacosx.m4
+m4/intlsolaris.m4
 m4/intmax.m4
 m4/inttypes_h.m4
 m4/inttypes-pri.m4
--- a/modules/localename	Mon Oct 22 02:34:07 2018 +0200
+++ b/modules/localename	Mon Oct 22 02:38:39 2018 +0200
@@ -4,6 +4,8 @@
 Files:
 lib/localename.h
 lib/localename.c
+lib/localename-table.h
+lib/localename-table.c
 m4/localename.m4
 m4/intlmacosx.m4
 m4/intlsolaris.m4
@@ -22,7 +24,7 @@
 gl_LOCALE_MODULE_INDICATOR([localename])
 
 Makefile.am:
-lib_SOURCES += localename.c
+lib_SOURCES += localename.c localename-table.c
 
 Include:
 "localename.h"