diff options
Diffstat (limited to 'lib/libc/locale/xlocale.c')
-rw-r--r-- | lib/libc/locale/xlocale.c | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/lib/libc/locale/xlocale.c b/lib/libc/locale/xlocale.c index ece0076..e114bac 100644 --- a/lib/libc/locale/xlocale.c +++ b/lib/libc/locale/xlocale.c @@ -6,17 +6,18 @@ * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions * are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -31,6 +32,7 @@ #include <pthread.h> #include <stdio.h> #include <string.h> +#include <runetype.h> #include "libc_private.h" #include "xlocale_private.h" @@ -50,6 +52,17 @@ extern struct xlocale_component __xlocale_global_messages; */ extern struct xlocale_component __xlocale_C_collate; extern struct xlocale_component __xlocale_C_ctype; + +#ifndef __NO_TLS +/* + * The locale for this thread. + */ +_Thread_local locale_t __thread_locale; +#endif +/* + * Flag indicating that one or more per-thread locales exist. + */ +int __has_thread_locale; /* * Private functions in setlocale.c. */ @@ -103,6 +116,7 @@ static locale_t thread_local_locale; static void init_key(void) { + pthread_key_create(&locale_info_key, xlocale_release); pthread_setspecific(locale_info_key, (void*)42); if (pthread_getspecific(locale_info_key) == (void*)42) { @@ -110,6 +124,8 @@ static void init_key(void) } else { fake_tls = 1; } + /* At least one per-thread locale has now been set. */ + __has_thread_locale = 1; __detect_path_locale(); } @@ -118,12 +134,14 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT; static locale_t get_thread_locale(void) { + _once(&once_control, init_key); return (fake_tls ? thread_local_locale : pthread_getspecific(locale_info_key)); } +#ifdef __NO_TLS locale_t __get_locale(void) { @@ -131,11 +149,13 @@ __get_locale(void) return (l ? l : &__xlocale_global_locale); } +#endif static void set_thread_locale(locale_t loc) { - pthread_once(&once_control, init_key); + + _once(&once_control, init_key); if (NULL != loc) { xlocale_retain((struct xlocale_refcounted*)loc); @@ -149,6 +169,10 @@ set_thread_locale(locale_t loc) } else { pthread_setspecific(locale_info_key, loc); } +#ifndef __NO_TLS + __thread_locale = loc; + __set_thread_rune_locale(loc); +#endif } /** @@ -159,6 +183,7 @@ static void destruct_locale(void *l) { locale_t loc = l; + for (int type=0 ; type<XLC_LAST ; type++) { if (loc->components[type]) { xlocale_release(loc->components[type]); @@ -177,6 +202,7 @@ static locale_t alloc_locale(void) { locale_t new = calloc(sizeof(struct _xlocale), 1); + new->header.destructor = destruct_locale; new->monetary_locale_changed = 1; new->numeric_locale_changed = 1; @@ -193,19 +219,23 @@ copyflags(locale_t new, locale_t old) static int dupcomponent(int type, locale_t base, locale_t new) { - /* Always copy from the global locale, since it has mutable components. */ + /* Always copy from the global locale, since it has mutable components. + */ struct xlocale_component *src = base->components[type]; + if (&__xlocale_global_locale == base) { new->components[type] = constructors[type](src->locale, new); if (new->components[type]) { - strncpy(new->components[type]->locale, src->locale, ENCODING_LEN); + strncpy(new->components[type]->locale, src->locale, + ENCODING_LEN); } } else if (base->components[type]) { new->components[type] = xlocale_retain(base->components[type]); } else { - /* If the component was NULL, return success - if base is a valid - * locale then the flag indicating that this isn't present should be - * set. If it isn't a valid locale, then we're stuck anyway. */ + /* If the component was NULL, return success - if base is a + * valid locale then the flag indicating that this isn't + * present should be set. If it isn't a valid locale, then + * we're stuck anyway. */ return 1; } return (0 != new->components[type]); @@ -244,9 +274,11 @@ locale_t newlocale(int mask, const char *locale, locale_t base) if (useenv) { realLocale = __get_locale_env(type); } - new->components[type] = constructors[type](realLocale, new); + new->components[type] = + constructors[type](realLocale, new); if (new->components[type]) { - strncpy(new->components[type]->locale, realLocale, ENCODING_LEN); + strncpy(new->components[type]->locale, + realLocale, ENCODING_LEN); } else { success = 0; break; @@ -319,7 +351,7 @@ const char *querylocale(int mask, locale_t loc) return (NULL); if (loc->components[type]) return (loc->components[type]->locale); - return "C"; + return ("C"); } /* |