summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/linuxthreads')
-rw-r--r--libpthread/linuxthreads/Makefile5
-rw-r--r--libpthread/linuxthreads/internals.h6
-rw-r--r--libpthread/linuxthreads/locale.c58
-rw-r--r--libpthread/linuxthreads/manager.c9
-rw-r--r--libpthread/linuxthreads/pthread.c14
5 files changed, 92 insertions, 0 deletions
diff --git a/libpthread/linuxthreads/Makefile b/libpthread/linuxthreads/Makefile
index 748776e71..880fda291 100644
--- a/libpthread/linuxthreads/Makefile
+++ b/libpthread/linuxthreads/Makefile
@@ -45,6 +45,11 @@ CSRC=attr.c cancel.c condvar.c errno.c events.c join.c lockfile.c manager.c \
mutex.c oldsemaphore.c pt-machine.c ptfork.c pthread.c \
ptlongjmp.c rwlock.c semaphore.c signals.c specific.c spinlock.c \
wrapsyscall.c #weaks.c
+
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+ CSRC += locale.c
+endif
+
COBJS=$(patsubst %.c,%.o, $(CSRC))
OBJS=$(COBJS)
diff --git a/libpthread/linuxthreads/internals.h b/libpthread/linuxthreads/internals.h
index 528acddc3..bce6b7efe 100644
--- a/libpthread/linuxthreads/internals.h
+++ b/libpthread/linuxthreads/internals.h
@@ -28,6 +28,9 @@
#include "pt-machine.h"
#include "semaphore.h"
#include "../linuxthreads_db/thread_dbP.h"
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <bits/uClibc_locale.h>
+#endif /* __UCLIBC_HAS_XLOCALE__ */
/* Use a funky version in a probably vein attempt at preventing gdb
* from dlopen()'ing glibc's libthread_db library... */
@@ -172,6 +175,9 @@ struct _pthread_descr_struct {
pthread_readlock_info *p_readlock_free; /* Free list of structs */
int p_untracked_readlock_count; /* Readlocks not tracked by list */
/* New elements must be added at the end. */
+#ifdef __UCLIBC_HAS_XLOCALE__
+ __locale_t locale; /* thread-specific locale from uselocale() only! */
+#endif /* __UCLIBC_HAS_XLOCALE__ */
} __attribute__ ((aligned(32))); /* We need to align the structure so that
doubles are aligned properly. This is 8
bytes on MIPS and 16 bytes on MIPS64.
diff --git a/libpthread/linuxthreads/locale.c b/libpthread/linuxthreads/locale.c
new file mode 100644
index 000000000..c3ebbc285
--- /dev/null
+++ b/libpthread/linuxthreads/locale.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 2003 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define _GNU_SOURCE
+#include <features.h>
+#include "pthread.h"
+#include "internals.h"
+#include <locale.h>
+#include <assert.h>
+#include <stdlib.h>
+
+extern struct _pthread_descr_struct __pthread_initial_thread;
+
+__locale_t __curlocale(void)
+{
+ pthread_descr self = thread_self();
+
+#ifdef NDEBUG
+ return THREAD_GETMEM (self, locale);
+#else
+ {
+ __locale_t r = THREAD_GETMEM (self, locale);
+
+ assert(r);
+
+ return r;
+ }
+#endif
+}
+
+__locale_t __curlocale_set(__locale_t newloc)
+{
+ __locale_t oldloc;
+ pthread_descr self = thread_self();
+
+ oldloc = THREAD_GETMEM (self, locale);
+
+ assert(newloc != LC_GLOBAL_LOCALE);
+ assert(oldloc);
+
+ THREAD_SETMEM (self, locale, newloc);
+
+ return oldloc;
+}
diff --git a/libpthread/linuxthreads/manager.c b/libpthread/linuxthreads/manager.c
index f1c9b93af..f7301bc52 100644
--- a/libpthread/linuxthreads/manager.c
+++ b/libpthread/linuxthreads/manager.c
@@ -134,6 +134,11 @@ int __pthread_manager(void *arg)
__pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
__pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;
+#ifdef __UCLIBC_HAS_XLOCALE__
+ /* Initialize thread's locale to the global locale. */
+ __pthread_manager_thread.locale = __global_locale;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
/* Block all signals except __pthread_sig_cancel and SIGTRAP */
sigfillset(&manager_mask);
sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
@@ -506,6 +511,10 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
new_thread->p_errnop = &new_thread->p_errno;
new_thread->p_h_errnop = &new_thread->p_h_errno;
+#ifdef __UCLIBC_HAS_XLOCALE__
+ /* Initialize thread's locale to the global locale. */
+ new_thread->locale = __global_locale;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
new_thread->p_guardaddr = guardaddr;
new_thread->p_guardsize = guardsize;
new_thread->p_self = new_thread;
diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c
index 22e3f6a9c..1c24cccd8 100644
--- a/libpthread/linuxthreads/pthread.c
+++ b/libpthread/linuxthreads/pthread.c
@@ -99,6 +99,10 @@ struct _pthread_descr_struct __pthread_initial_thread = {
NULL, /* pthread_readlock_info *p_readlock_list; */
NULL, /* pthread_readlock_info *p_readlock_free; */
0 /* int p_untracked_readlock_count; */
+#ifdef __UCLIBC_HAS_XLOCALE__
+ ,
+ NULL, /* __locale_t locale; */
+#endif /* __UCLIBC_HAS_XLOCALE__ */
};
/* Descriptor of the manager thread; none of this is used but the error
@@ -151,6 +155,10 @@ struct _pthread_descr_struct __pthread_manager_thread = {
NULL, /* pthread_readlock_info *p_readlock_list; */
NULL, /* pthread_readlock_info *p_readlock_free; */
0 /* int p_untracked_readlock_count; */
+#ifdef __UCLIBC_HAS_XLOCALE__
+ ,
+ NULL, /* __locale_t locale; */
+#endif /* __UCLIBC_HAS_XLOCALE__ */
};
/* Pointer to the main thread (the father of the thread manager thread) */
@@ -318,6 +326,12 @@ static void pthread_initialize(void)
/* The errno/h_errno variable of the main thread are the global ones. */
__pthread_initial_thread.p_errnop = &_errno;
__pthread_initial_thread.p_h_errnop = &_h_errno;
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+ /* The locale of the main thread is the current locale in use. */
+ __pthread_initial_thread.locale = __curlocale_var;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
/* Play with the stack size limit to make sure that no stack ever grows
beyond STACK_SIZE minus two pages (one page for the thread descriptor
immediately beyond, and one page to act as a guard page). */