aboutsummaryrefslogtreecommitdiff
path: root/nptl/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-05-19 07:08:23 +0000
committerUlrich Drepper <drepper@redhat.com>2007-05-19 07:08:23 +0000
commitdf94b6412e0628cd577da0ce5626358a3967ee44 (patch)
tree3b969d3e4175fe3a72f824c482d8c9f9a3b3bf3e /nptl/sysdeps
parent2acd01acb10d0c0113f87bf7e787e0854498269d (diff)
downloadglibc-df94b6412e0628cd577da0ce5626358a3967ee44.tar
glibc-df94b6412e0628cd577da0ce5626358a3967ee44.tar.gz
glibc-df94b6412e0628cd577da0ce5626358a3967ee44.tar.bz2
glibc-df94b6412e0628cd577da0ce5626358a3967ee44.zip
* elf/dl-close.c (_dl_close_worker): When removing object from
global scope, wait for all lookups to finish afterwards. * elf/dl-open.c (add_to_global): When global scope array must grow, allocate a new one and free old array only after all lookups finish. * elf/dl-runtime.c (_dl_fixup): Protect using global scope. (_dl_lookup_symbol_x): Likewise. * elf/dl-support.c: Define _dl_wait_lookup_done. * sysdeps/generic/ldsodefs.h (struct rtld_global): Add _dl_wait_lookup_done.
Diffstat (limited to 'nptl/sysdeps')
-rw-r--r--nptl/sysdeps/i386/tls.h33
-rw-r--r--nptl/sysdeps/pthread/pthread-functions.h2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c7
-rw-r--r--nptl/sysdeps/x86_64/tls.h26
4 files changed, 66 insertions, 2 deletions
diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h
index d5b3797e69..d9044f3fde 100644
--- a/nptl/sysdeps/i386/tls.h
+++ b/nptl/sysdeps/i386/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. nptl/i386 version.
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,6 +27,7 @@
# include <stdint.h>
# include <stdlib.h>
# include <list.h>
+# include <sysdep.h>
/* Type for the dtv. */
@@ -51,6 +52,7 @@ typedef struct
uintptr_t sysinfo;
uintptr_t stack_guard;
uintptr_t pointer_guard;
+ int gscope_flag;
} tcbhead_t;
# define TLS_MULTIPLE_THREADS_IN_TCB 1
@@ -431,6 +433,35 @@ union user_desc_init
= THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
+/* Get and set the global scope generation counter in the TCB head. */
+#define THREAD_GSCOPE_FLAG_UNUSED 0
+#define THREAD_GSCOPE_FLAG_USED 1
+#define THREAD_GSCOPE_FLAG_WAIT 2
+#define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ { int __res; \
+ asm volatile ("xchg %0, %%gs:%P1" \
+ : "=r" (__res) \
+ : "i" (offsetof (struct pthread, header.gscope_flag)), \
+ "0" (THREAD_GSCOPE_FLAG_UNUSED)); \
+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \
+ } \
+ while (0)
+#define THREAD_GSCOPE_SET_FLAG() \
+ THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED)
+#ifdef PTR_DEMANGLE
+# define THREAD_GSCOPE_WAIT() \
+ do { void (*ptr) (void) = GL(dl_wait_lookup_done); \
+ PTR_DEMANGLE (ptr); \
+ ptr (); \
+ } while (0)
+#else
+# define THREAD_GSCOPE_WAIT() \
+ GL(dl_wait_lookup_done) ()
+#endif
+
+
#endif /* __ASSEMBLER__ */
#endif /* tls.h */
diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h
index a13b937032..f0eddd3053 100644
--- a/nptl/sysdeps/pthread/pthread-functions.h
+++ b/nptl/sysdeps/pthread/pthread-functions.h
@@ -97,7 +97,7 @@ struct pthread_functions
void (*ptr__nptl_deallocate_tsd) (void);
int (*ptr__nptl_setxid) (struct xid_command *);
void (*ptr_freeres) (void);
- void (*ptr_wait_lookup_done) (int);
+ void (*ptr_wait_lookup_done) (void);
};
/* Variable in libc.so. */
diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
index 92a188a2f3..25509eb3d6 100644
--- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
+++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
@@ -26,6 +26,7 @@
#include <pthreadP.h>
#include <bits/libc-lock.h>
#include <sysdep.h>
+#include <ldsodefs.h>
#ifdef TLS_MULTIPLE_THREADS_IN_TCB
@@ -70,6 +71,12 @@ __libc_pthread_init (ptr, reclaim, functions)
dest->parr[cnt] = p;
}
__libc_pthread_functions_init = 1;
+
+# ifdef RTLD_NOT_MANGLED
+ GL(dl_wait_lookup_done) = functions->ptr_wait_lookup_done;
+# else
+ GL(dl_wait_lookup_done) = __libc_pthread_functions.ptr_wait_lookup_done;
+# endif
#endif
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
diff --git a/nptl/sysdeps/x86_64/tls.h b/nptl/sysdeps/x86_64/tls.h
index 0b5aeb00ff..00c9abbfcb 100644
--- a/nptl/sysdeps/x86_64/tls.h
+++ b/nptl/sysdeps/x86_64/tls.h
@@ -26,6 +26,7 @@
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
+# include <sysdep.h>
/* Type for the dtv. */
@@ -47,6 +48,7 @@ typedef struct
dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
int multiple_threads;
+ int gscope_flag;
uintptr_t sysinfo;
uintptr_t stack_guard;
uintptr_t pointer_guard;
@@ -337,6 +339,30 @@ typedef struct
= THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
+/* Get and set the global scope generation counter in the TCB head. */
+#define THREAD_GSCOPE_FLAG_UNUSED 0
+#define THREAD_GSCOPE_FLAG_USED 1
+#define THREAD_GSCOPE_FLAG_WAIT 2
+#define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ { int __res; \
+ asm volatile ("xchgl %0, %%fs:%P1" \
+ : "=r" (__res) \
+ : "i" (offsetof (struct pthread, header.gscope_flag)), \
+ "0" (THREAD_GSCOPE_FLAG_UNUSED)); \
+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \
+ } \
+ while (0)
+#define THREAD_GSCOPE_SET_FLAG() \
+ THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED)
+#define THREAD_GSCOPE_WAIT() \
+ do { void (*ptr) (void) = GL(dl_wait_lookup_done); \
+ PTR_DEMANGLE (ptr); \
+ ptr (); \
+ } while (0)
+
+
#endif /* __ASSEMBLER__ */
#endif /* tls.h */