summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authortheraven <theraven@FreeBSD.org>2012-02-14 12:03:23 +0000
committertheraven <theraven@FreeBSD.org>2012-02-14 12:03:23 +0000
commitb529e734cb0e714064ede8ada785785cf36328b3 (patch)
treed83544c2e798a9a440baf38564df616970b2b0f5 /lib
parentbcfaf51260694a128c1375064baa2ce595f66f24 (diff)
downloadFreeBSD-src-b529e734cb0e714064ede8ada785785cf36328b3.zip
FreeBSD-src-b529e734cb0e714064ede8ada785785cf36328b3.tar.gz
Cleanup of xlocale:
- Address performance regressions encountered by das@ by caching per-thread data in TLS where available. - Add a __NO_TLS flag to cdefs.h to indicate where not available. - Reorganise the xlocale.h definitions into xlocale/*.h so that they can be included from multiple places. - Export the POSIX2008 subset of xlocale when POSIX2008 says it should be exported, independently of whether xlocale.h is included. - Fix the bug where programs using ctype functions always assumed ASCII unless recompiled. - Fix some style(9) violations. Reviewed by: brooks (mentor) Approved by: dim (mentor)
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/locale/Symbol.map1
-rw-r--r--lib/libc/locale/setrunelocale.c29
-rw-r--r--lib/libc/locale/table.c2
-rw-r--r--lib/libc/locale/xlocale.c64
-rw-r--r--lib/libc/locale/xlocale_private.h46
5 files changed, 113 insertions, 29 deletions
diff --git a/lib/libc/locale/Symbol.map b/lib/libc/locale/Symbol.map
index 01242b6..a65acc2 100644
--- a/lib/libc/locale/Symbol.map
+++ b/lib/libc/locale/Symbol.map
@@ -194,6 +194,7 @@ FBSD_1.3 {
wcstoull_l;
wcstoumax_l;
__runes_for_locale;
+ _ThreadRuneLocale;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index 61ce5d9..d2e3320 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -38,6 +38,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#define __RUNETYPE_INTERNAL 1
+
#include <runetype.h>
#include <errno.h>
#include <limits.h>
@@ -50,6 +52,15 @@ __FBSDID("$FreeBSD$");
#include "mblocal.h"
#include "setlocale.h"
+#undef _CurrentRuneLocale
+extern _RuneLocale const *_CurrentRuneLocale;
+#ifndef __NO_TLS
+/*
+ * A cached version of the runes for this thread. Used by ctype.h
+ */
+_Thread_local const _RuneLocale *_ThreadRuneLocale;
+#endif
+
extern int __mb_sb_limit;
extern _RuneLocale *_Read_RuneMagi(FILE *);
@@ -72,7 +83,8 @@ static void destruct_ctype(void *v)
free(l->runes);
free(l);
}
-_RuneLocale *__getCurrentRuneLocale(void)
+
+const _RuneLocale *__getCurrentRuneLocale(void)
{
return XLOCALE_CTYPE(__get_locale())->runes;
}
@@ -168,10 +180,22 @@ __wrap_setrunelocale(const char *locale)
}
__mb_cur_max = __xlocale_global_ctype.__mb_cur_max;
__mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit;
+ _CurrentRuneLocale = __xlocale_global_ctype.runes;
return (_LDP_LOADED);
}
-void *__ctype_load(const char *locale, locale_t unused)
+void
+__set_thread_rune_locale(locale_t loc) {
+
+ if (loc == NULL) {
+ _ThreadRuneLocale = &_DefaultRuneLocale;
+ } else {
+ _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes;
+ }
+}
+void *
+__ctype_load(const char *locale, locale_t unused)
{
+#ifndef __NO_TLS
struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1);
l->header.header.destructor = destruct_ctype;
if (__setrunelocale(l, locale))
@@ -180,4 +204,5 @@ void *__ctype_load(const char *locale, locale_t unused)
return NULL;
}
return l;
+#endif
}
diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c
index 8c876e9..e89d479 100644
--- a/lib/libc/locale/table.c
+++ b/lib/libc/locale/table.c
@@ -251,7 +251,7 @@ const _RuneLocale _DefaultRuneLocale = {
};
#undef _CurrentRuneLocale
-_RuneLocale *_CurrentRuneLocale = (_RuneLocale*)&_DefaultRuneLocale;
+const _RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
_RuneLocale *
__runes_for_locale(locale_t locale, int *mb_sb_limit)
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");
}
/*
diff --git a/lib/libc/locale/xlocale_private.h b/lib/libc/locale/xlocale_private.h
index 272d15e..0110060 100644
--- a/lib/libc/locale/xlocale_private.h
+++ b/lib/libc/locale/xlocale_private.h
@@ -8,16 +8,16 @@
* 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.
+ * 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)
@@ -85,14 +85,14 @@ struct _xlocale {
struct xlocale_refcounted header;
/** Components for the locale. */
struct xlocale_component *components[XLC_LAST];
- /** Flag indicating if components[XLC_MONETARY] has changed since the last
- * call to localeconv_l() with this locale. */
+ /** Flag indicating if components[XLC_MONETARY] has changed since the
+ * last call to localeconv_l() with this locale. */
int monetary_locale_changed;
/** Flag indicating whether this locale is actually using a locale for
* LC_MONETARY (1), or if it should use the C default instead (0). */
int using_monetary_locale;
- /** Flag indicating if components[XLC_NUMERIC] has changed since the last
- * call to localeconv_l() with this locale. */
+ /** Flag indicating if components[XLC_NUMERIC] has changed since the
+ * last call to localeconv_l() with this locale. */
int numeric_locale_changed;
/** Flag indicating whether this locale is actually using a locale for
* LC_NUMERIC (1), or if it should use the C default instead (0). */
@@ -170,12 +170,38 @@ extern struct _xlocale __xlocale_global_locale;
extern struct _xlocale __xlocale_C_locale;
/**
+ * Caches the rune table in TLS for fast access.
+ */
+void __set_thread_rune_locale(locale_t loc);
+/**
+ * Flag indicating whether a per-thread locale has been set. If no per-thread
+ * locale has ever been set, then we always use the global locale.
+ */
+extern int __has_thread_locale;
+#ifndef __NO_TLS
+/**
+ * The per-thread locale. Avoids the need to use pthread lookup functions when
+ * getting the per-thread locale.
+ */
+extern __thread locale_t __thread_locale;
+
+/**
* Returns the current locale for this thread, or the global locale if none is
* set. The caller does not have to free the locale. The return value from
* this call is not guaranteed to remain valid after the locale changes. As
* such, this should only be called within libc functions.
*/
+inline locale_t __get_locale(void)
+{
+
+ if (!__has_thread_locale) {
+ return (&__xlocale_global_locale);
+ }
+ return (__thread_locale ? __thread_locale : &__xlocale_global_locale);
+}
+#else
locale_t __get_locale(void);
+#endif
/**
* Two magic values are allowed for locale_t objects. NULL and -1. This
OpenPOWER on IntegriCloud