# HG changeset patch # User Bruno Haible # Date 1540168719 -7200 # Node ID 1ebb12ec25e0756dc7d9bf74b38b5b6a3a010e81 # Parent 33d4c96d8486d4f03e7ae7e2ff2da70ae6ebcaa3 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. diff -r 33d4c96d8486 -r 1ebb12ec25e0 ChangeLog --- 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 + + 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 Small update from gettext. diff -r 33d4c96d8486 -r 1ebb12ec25e0 lib/localename-table.c --- /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 . */ + +/* Written by Bruno Haible , 2018. */ + +#include + +#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */ + +/* Specification. */ +#include "localename-table.h" + +#include + +/* 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 diff -r 33d4c96d8486 -r 1ebb12ec25e0 lib/localename-table.h --- /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 . */ + +/* Written by Bruno Haible , 2018. */ + +#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */ + +# include +# include + +# 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 diff -r 33d4c96d8486 -r 1ebb12ec25e0 lib/localename.c --- 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 -# include +# 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; diff -r 33d4c96d8486 -r 1ebb12ec25e0 m4/intlsolaris.m4 --- 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 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 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 + 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 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 - 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 ]) diff -r 33d4c96d8486 -r 1ebb12ec25e0 modules/gettext --- 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 diff -r 33d4c96d8486 -r 1ebb12ec25e0 modules/localename --- 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"