diff options
29 files changed, 383 insertions, 113 deletions
diff --git a/libpthread/nptl/Makefile.in b/libpthread/nptl/Makefile.in index 9761f9670..4e1db3dcc 100644 --- a/libpthread/nptl/Makefile.in +++ b/libpthread/nptl/Makefile.in @@ -150,7 +150,7 @@ CFLAGS-msgrcv.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-msgsnd.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-tcdrain.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pt-system.c = -fexceptions +CFLAGS-pt-system.c = -fexceptions -I./libc/stdlib # # The rest of this file is uClibc specific. @@ -235,7 +235,7 @@ libpthread_so_SRC = $(patsubst %, $(PTHREAD_DIR)/%.c, \ $(libpthread-misc-routines), $(libpthread-routines))) libc-static-y += $(patsubst %.c, $(PTHREAD_OUT)/%.o, alloca_cutoff.c \ - forward.c libc-cancellation.c) + libc-cancellation.c) libc-shared-y += $(patsubst %.c, $(PTHREAD_OUT)/%.oS, forward.c \ libc-cancellation.c) libpthread-nonshared-y += $(patsubst %,$(PTHREAD_OUT)/%.oS,$(libpthread_static_SRC)) @@ -272,7 +272,7 @@ endif $(do_ar) ifeq ($(DOPIC),y) -$(top_builddir)lib/libpthread.a: $(libpthread-a-y:.o=.oS) +$(top_builddir)lib/libpthread.a: $(libpthread-a-y:.o=.os) else $(top_builddir)lib/libpthread.a: $(libpthread-a-y) endif @@ -295,7 +295,7 @@ $(PTHREAD_OUT)/pthread-errnos.s: $(PTHREAD_OUT)/pthread-errnos.c $(PTHREAD_OUT)/pthread-errnos.h: $(PTHREAD_OUT)/pthread-errnos.s @sed -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $(PTHREAD_OUT)/pthread-errnos.h -nptl_headers: +nptl_headers_bootstrap: @sed 's/\(.*\)/"\1\\n"/' $(PTDIR)/Banner > $(PTDIR)/banner.h @echo "#define VERSION \""$(VERSION)"\"" > $(PTDIR)/version.h $(LN) -sf ../$(PTDIR)/sysdeps/pthread/pthread.h $(top_builddir)include/ @@ -305,6 +305,8 @@ nptl_headers: $(LN) -sf ../../$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/bits/pthreadtypes.h $(top_builddir)include/bits/ $(LN) -sf ../../$(PTDIR)/sysdeps/pthread/bits/libc-lock.h $(top_builddir)include/bits/ $(LN) -sf ../../$(PTDIR)/sysdeps/pthread/bits/stdio-lock.h $(top_builddir)include/bits/ + +nptl_headers: ifeq ($(shell $(CC) --help >& /dev/null && echo yes),yes) $(MAKE) $(PTHREAD_OUT)/pthread-errnos.h endif @@ -315,4 +317,4 @@ nptl_headers_clean: $(PTHREAD_OUT)/pthread-errnos.{c,h,s} libpthread_clean: - $(RM) $(PTHREAD_OUT)/*.{o,os,oS} + $(RM) $(PTHREAD_OUT)/*.{o,os,oS,a} diff --git a/libpthread/nptl/cancellation.c b/libpthread/nptl/cancellation.c index 59e16b9e1..1d28d383f 100644 --- a/libpthread/nptl/cancellation.c +++ b/libpthread/nptl/cancellation.c @@ -32,7 +32,6 @@ __pthread_enable_asynccancel (void) struct pthread *self = THREAD_SELF; int oldval = THREAD_GETMEM (self, cancelhandling); -//printf("%s\n", __FUNCTION__); while (1) { int newval = oldval | CANCELTYPE_BITMASK; @@ -65,7 +64,6 @@ void internal_function attribute_hidden __pthread_disable_asynccancel (int oldtype) { -//printf("%s\n", __FUNCTION__); /* If asynchronous cancellation was enabled before we do not have anything to do. */ if (oldtype & CANCELTYPE_BITMASK) diff --git a/libpthread/nptl/descr.h b/libpthread/nptl/descr.h index 474fa9caa..12e48a83c 100644 --- a/libpthread/nptl/descr.h +++ b/libpthread/nptl/descr.h @@ -96,7 +96,7 @@ struct pthread_unwind_buf struct xid_command { int syscall_no; - long id[3]; + long int id[3]; volatile int cntr; }; @@ -160,8 +160,11 @@ struct pthread /* Bit set if thread terminated and TCB is freed. */ #define TERMINATED_BIT 5 #define TERMINATED_BITMASK 0x20 + /* Bit set if thread is supposed to change XID. */ +#define SETXID_BIT 6 +#define SETXID_BITMASK 0x40 /* Mask for the rest. Helps the compiler to optimize. */ -#define CANCEL_RESTMASK 0xffffffc0 +#define CANCEL_RESTMASK 0xffffff80 #define CANCEL_ENABLED_AND_CANCELED(value) \ (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \ @@ -202,6 +205,9 @@ struct pthread /* Lock to synchronize access to the descriptor. */ lll_lock_t lock; + /* Lock for synchronizing setxid calls. */ + lll_lock_t setxid_futex; + #if HP_TIMING_AVAIL /* Offset of the CPU clock at start thread start time. */ hp_timing_t cpuclock_offset; @@ -254,12 +260,11 @@ struct pthread /* Resolver state. */ struct __res_state res; - /* If you add fields after the res field above, please adjust - the following macro. */ -#define PTHREAD_STRUCT_END_PADDING \ - (sizeof (struct pthread) - offsetof (struct pthread, res) \ - - sizeof (((struct pthread *) 0)->res)) + /* This member must be last. */ + char end_padding[]; +#define PTHREAD_STRUCT_END_PADDING \ + (sizeof (struct pthread) - offsetof (struct pthread, end_padding)) } __attribute ((aligned (TCB_ALIGNMENT))); diff --git a/libpthread/nptl/forward.c b/libpthread/nptl/forward.c index 843096841..5b71f8e67 100644 --- a/libpthread/nptl/forward.c +++ b/libpthread/nptl/forward.c @@ -123,25 +123,25 @@ FORWARD (pthread_setschedparam, FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) +libc_hidden_proto(pthread_mutex_init) FORWARD (pthread_mutex_init, (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), (mutex, mutexattr), 0) -libc_hidden_proto(pthread_mutex_init) strong_alias(pthread_mutex_init, __pthread_mutex_init) libc_hidden_def(pthread_mutex_init) -FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) libc_hidden_proto(pthread_mutex_trylock) +FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) libc_hidden_def(pthread_mutex_trylock) -FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) libc_hidden_proto(pthread_mutex_lock) +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) strong_alias(pthread_mutex_lock, __pthread_mutex_lock) libc_hidden_def(pthread_mutex_lock) -FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) libc_hidden_proto(pthread_mutex_unlock) +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) libc_hidden_def(pthread_mutex_unlock) diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c index ead1a3fba..cd5d39314 100644 --- a/libpthread/nptl/init.c +++ b/libpthread/nptl/init.c @@ -271,6 +271,17 @@ __pthread_initialize_minimal_internal (void) (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask, NULL, _NSIG / 8); + /* Get the size of the static and alignment requirements for the TLS + block. */ + size_t static_tls_align; + _dl_get_tls_static_info (&__static_tls_size, &static_tls_align); + + /* Make sure the size takes all the alignments into account. */ + if (STACK_ALIGN > static_tls_align) + static_tls_align = STACK_ALIGN; + __static_tls_align_m1 = static_tls_align - 1; + + __static_tls_size = roundup (__static_tls_size, static_tls_align); /* Determine the default allowed stack size. This is the size used in case the user does not specify one. */ @@ -279,29 +290,28 @@ __pthread_initialize_minimal_internal (void) || limit.rlim_cur == RLIM_INFINITY) /* The system limit is not usable. Use an architecture-specific default. */ - __default_stacksize = ARCH_STACK_DEFAULT_SIZE; + limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE; else if (limit.rlim_cur < PTHREAD_STACK_MIN) /* The system limit is unusably small. Use the minimal size acceptable. */ - __default_stacksize = PTHREAD_STACK_MIN; - else - { - /* Round the resource limit up to page size. */ - const uintptr_t pagesz = sysconf (_SC_PAGESIZE); - __default_stacksize = (limit.rlim_cur + pagesz - 1) & -pagesz; - } + limit.rlim_cur = PTHREAD_STACK_MIN; - /* Get the size of the static and alignment requirements for the TLS - block. */ - size_t static_tls_align; - _dl_get_tls_static_info (&__static_tls_size, &static_tls_align); + /* Make sure it meets the minimum size that allocate_stack + (allocatestack.c) will demand, which depends on the page size. */ + const uintptr_t pagesz = sysconf (_SC_PAGESIZE); + const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; + if (limit.rlim_cur < minstack) + limit.rlim_cur = minstack; - /* Make sure the size takes all the alignments into account. */ - if (STACK_ALIGN > static_tls_align) - static_tls_align = STACK_ALIGN; - __static_tls_align_m1 = static_tls_align - 1; + /* Round the resource limit up to page size. */ + limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz; + __default_stacksize = limit.rlim_cur; - __static_tls_size = roundup (__static_tls_size, static_tls_align); +#ifdef SHARED + /* Transfer the old value from the dynamic linker's internal location. */ + *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); + GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; +#endif GL(dl_init_static_tls) = &__pthread_init_static_tls; diff --git a/libpthread/nptl/pt-system.c b/libpthread/nptl/pt-system.c index b3b45ab93..09a08ec24 100644 --- a/libpthread/nptl/pt-system.c +++ b/libpthread/nptl/pt-system.c @@ -23,6 +23,9 @@ #include "pthreadP.h" +extern __typeof(system) __libc_system; +#include <system.c> + int system (const char *line) { diff --git a/libpthread/nptl/pthread_cancel.c b/libpthread/nptl/pthread_cancel.c index 41543fd78..a13af56b3 100644 --- a/libpthread/nptl/pthread_cancel.c +++ b/libpthread/nptl/pthread_cancel.c @@ -31,13 +31,11 @@ pthread_cancel (th) { volatile struct pthread *pd = (volatile struct pthread *) th; -//printf("%s:%d\n", __FUNCTION__, __LINE__); /* Make sure the descriptor is valid. */ if (INVALID_TD_P (pd)) /* Not a valid thread handle. */ return ESRCH; -//printf("%s:%d\n", __FUNCTION__, __LINE__); #ifdef SHARED pthread_cancel_init (); #endif @@ -49,20 +47,17 @@ pthread_cancel (th) oldval = pd->cancelhandling; newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; -//printf("%s:%d\n", __FUNCTION__, __LINE__); /* Avoid doing unnecessary work. The atomic operation can potentially be expensive if the bug has to be locked and remote cache lines have to be invalidated. */ if (oldval == newval) break; -//printf("%s:%d newval = %x\n", __FUNCTION__, __LINE__, newval); /* If the cancellation is handled asynchronously just send a signal. We avoid this if possible since it's more expensive. */ if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) { -//printf("%s:%d\n", __FUNCTION__, __LINE__); /* Mark the cancellation as "in progress". */ atomic_bit_set (&pd->cancelhandling, CANCELING_BIT); @@ -81,23 +76,19 @@ pthread_cancel (th) val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); -//printf("%s:%d\n", __FUNCTION__, __LINE__); #else # ifdef __NR_tgkill val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); -//printf("%s:%d\n", __FUNCTION__, __LINE__); if (INTERNAL_SYSCALL_ERROR_P (val, err) && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) # endif val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCANCEL); -//printf("%s:%d\n", __FUNCTION__, __LINE__); #endif if (INTERNAL_SYSCALL_ERROR_P (val, err)) result = INTERNAL_SYSCALL_ERRNO (val, err); -//printf("%s:%d\n", __FUNCTION__, __LINE__); break; } @@ -106,7 +97,6 @@ pthread_cancel (th) atomically since other bits could be modified as well. */ while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval, oldval)); -//printf("%s:%d\n", __FUNCTION__, __LINE__); return result; } diff --git a/libpthread/nptl/res.c b/libpthread/nptl/res.c index ba4f81d06..37529899e 100644 --- a/libpthread/nptl/res.c +++ b/libpthread/nptl/res.c @@ -17,8 +17,9 @@ 02111-1307 USA. */ #include <features.h> -#include <resolv.h> + #include <tls.h> +#include <resolv.h> struct __res_state * __res_state (void) diff --git a/libpthread/nptl/sysdeps/generic/dl-support.c b/libpthread/nptl/sysdeps/generic/dl-support.c index 496694ca4..b8f0c07a6 100644 --- a/libpthread/nptl/sysdeps/generic/dl-support.c +++ b/libpthread/nptl/sysdeps/generic/dl-support.c @@ -35,16 +35,11 @@ void internal_function _dl_aux_init (ElfW(auxv_t) *av) { - for (; av->a_type != AT_NULL; ++av) - switch (av->a_type) - { - case AT_PHDR: - GL(dl_phdr) = (void *) av->a_un.a_val; - break; - case AT_PHNUM: - GL(dl_phnum) = av->a_un.a_val; - break; - } + /* Get the program headers base address from the aux vect */ + GL(dl_phdr) = (ElfW(Phdr) *) av[AT_PHDR].a_un.a_val; + + /* Get the number of program headers from the aux vect */ + GL(dl_phnum) = (size_t) av[AT_PHNUM].a_un.a_val; } /* Initialize static TLS area and DTV for current (only) thread. diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.c b/libpthread/nptl/sysdeps/generic/dl-tls.c index 1a045ba5b..ad2e84ea3 100644 --- a/libpthread/nptl/sysdeps/generic/dl-tls.c +++ b/libpthread/nptl/sysdeps/generic/dl-tls.c @@ -24,6 +24,8 @@ #include <tls.h> #include <dl-tls.h> #include <ldsodefs.h> +#include <dl-elf.h> +#include <dl-hash.h> #include <assert.h> #include <link.h> @@ -66,6 +68,86 @@ void *_dl_memalign(size_t alignment, size_t bytes) return _dl_malloc(bytes); } + +/* + * We are trying to perform a static TLS relocation in MAP, but it was + * dynamically loaded. This can only work if there is enough surplus in + * the static TLS area already allocated for each running thread. If this + * object's TLS segment is too big to fit, we fail. If it fits, + * we set MAP->l_tls_offset and return. + * This function intentionally does not return any value but signals error + * directly, as static TLS should be rare and code handling it should + * not be inlined as much as possible. + */ + + +void +internal_function __attribute_noinline__ +_dl_allocate_static_tls (struct link_map *map) +{ + /* If the alignment requirements are too high fail. */ + if (map->l_tls_align > _dl_tls_static_align) + { +fail: + _dl_dprintf(_dl_debug_file, "cannot allocate memory in static TLS block"); + _dl_exit(30); + } + +# if TLS_TCB_AT_TP + size_t freebytes; + size_t n; + size_t blsize; + + freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE; + + blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset; + if (freebytes < blsize) + goto fail; + + n = (freebytes - blsize) / map->l_tls_align; + + size_t offset = _dl_tls_static_used + (freebytes - n * map->l_tls_align + - map->l_tls_firstbyte_offset); + + map->l_tls_offset = _dl_tls_static_used = offset; +# elif TLS_DTV_AT_TP + size_t used; + size_t check; + + size_t offset = roundup (_dl_tls_static_used, map->l_tls_align); + used = offset + map->l_tls_blocksize; + check = used; + + /* dl_tls_static_used includes the TCB at the beginning. */ + if (check > _dl_tls_static_size) + goto fail; + + map->l_tls_offset = offset; + _dl_tls_static_used = used; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* + * If the object is not yet relocated we cannot initialize the + * static TLS region. Delay it. + */ + if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE) + { +#ifdef SHARED + /* + * Update the slot information data for at least the generation of + * the DSO we are allocating data for. + */ + if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0)) + (void) _dl_update_slotinfo (map->l_tls_modid); +#endif + _dl_init_static_tls (map); + } + else + map->l_need_tls_init = 1; +} + size_t internal_function _dl_next_tls_modid (void) diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c index 3b58ce21f..d302d31c9 100644 --- a/libpthread/nptl/sysdeps/generic/libc-tls.c +++ b/libpthread/nptl/sysdeps/generic/libc-tls.c @@ -26,13 +26,14 @@ #include <elf.h> #include <link.h> #include <string.h> +#include <stdlib.h> #ifdef SHARED #error makefile bug, this file is for static only #endif -#ifdef USE_TLS +#if USE_TLS extern ElfW(Phdr) *_dl_phdr; extern size_t _dl_phnum; @@ -191,7 +192,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0); # elif TLS_DTV_AT_TP INSTALL_DTV (tlsblock, static_dtv); - const char *lossage = TLS_INIT_TP (tlsblock, 0); + const char *lossage = (char *)TLS_INIT_TP (tlsblock, 0); # else # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" # endif diff --git a/libpthread/nptl/sysdeps/generic/sysdep.h b/libpthread/nptl/sysdeps/generic/sysdep.h index 7c2d76b92..0bbcf9a69 100644 --- a/libpthread/nptl/sysdeps/generic/sysdep.h +++ b/libpthread/nptl/sysdeps/generic/sysdep.h @@ -17,6 +17,25 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#ifndef C_LABEL + +/* Define a macro we can use to construct the asm name for a C symbol. */ +#ifdef NO_UNDERSCORES +#ifdef __STDC__ +#define C_LABEL(name) name##: +#else +#define C_LABEL(name) name/**/: +#endif +#else +#ifdef __STDC__ +#define C_LABEL(name) _##name##: +#else +#define C_LABEL(name) _/**/name/**/: +#endif +#endif + +#endif + #ifdef __ASSEMBLER__ /* Mark the end of function named SYM. This is used on some platforms to generate correct debugging information. */ @@ -41,6 +60,7 @@ # define cfi_register(r1, r2) .cfi_register r1, r2 # define cfi_return_column(reg) .cfi_return_column reg # define cfi_restore(reg) .cfi_restore reg +# define cfi_same_value(reg) .cfi_same_value reg # define cfi_undefined(reg) .cfi_undefined reg # define cfi_remember_state .cfi_remember_state # define cfi_restore_state .cfi_restore_state @@ -57,6 +77,7 @@ # define cfi_register(r1, r2) # define cfi_return_column(reg) # define cfi_restore(reg) +# define cfi_same_value(reg) # define cfi_undefined(reg) # define cfi_remember_state # define cfi_restore_state diff --git a/libpthread/nptl/sysdeps/pthread/Makefile.in b/libpthread/nptl/sysdeps/pthread/Makefile.in index a0ed8c00c..db3cebd4d 100644 --- a/libpthread/nptl/sysdeps/pthread/Makefile.in +++ b/libpthread/nptl/sysdeps/pthread/Makefile.in @@ -17,15 +17,25 @@ libpthread_CSRC = pthread_barrier_wait.c pthread_cond_broadcast.c \ pthread_rwlock_timedwrlock.c pthread_rwlock_unlock.c \ pthread_rwlock_wrlock.c pthread_sigmask.c \ pthread_spin_destroy.c pthread_spin_init.c \ - pthread_spin_unlock.c pt-sigaction.c pt-sigfillset.c \ - pt-sigprocmask.c unwind-forcedunwind.c pt-longjmp.c + pthread_spin_unlock.c pt-sigfillset.c \ + unwind-forcedunwind.c pt-longjmp.c ifeq ($(TARGET_ARCH),i386) libpthread_CSRC += pthread_once.c endif + ifeq ($(TARGET_ARCH),sh) -libpthread_CSRC += pthread_once.c +SH_PTHREAD_EXCLUDE_LIST = pthread_spin_unlock.c pthread_spin_init.c \ + pthread_rwlock_wrlock.c pthread_rwlock_rdlock.c \ + pthread_rwlock_unlock.c pt-longjmp.c \ + pthread_barrier_wait.c pthread_cond_broadcast.c \ + pthread_cond_signal.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_timedwrlock.c + +libpthread_CSRC := $(filter-out $(SH_PTHREAD_EXCLUDE_LIST),$(libpthread_CSRC)) endif + ifeq ($(TARGET_ARCH),x86_64) libpthread_CSRC += pthread_once.c endif @@ -74,6 +84,10 @@ pthread_OBJ = $(patsubst %.c, $(pthread_OUT)/%.o, $(libpthread_CSRC)) libpthread-a-y += $(pthread_OBJ) libpthread-so-y += $(pthread_OBJ:.o=.oS) +libpthread-so-y += $(pthread_OUT)/pt-sigaction.oS $(pthread_OUT)/pt-sigprocmask.oS + +CFLAGS-sigaction.c = -I$(top_srcdir)libc/signal +libc-y += $(pthread_OUT)/sigaction.o librt-a-y += $(pthread_OUT)/librt-cancellation.o librt-so-y += $(pthread_OUT)/librt-cancellation.oS \ diff --git a/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h b/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h index d043a0d2e..fb085f5be 100644 --- a/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h +++ b/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h @@ -409,6 +409,9 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer /* Normal cleanup handling, based on C cleanup attribute. */ extern __inline void +__libc_cleanup_routine (struct __pthread_cleanup_frame *f); + +extern __inline void __libc_cleanup_routine (struct __pthread_cleanup_frame *f) { if (f->__do_it) @@ -528,10 +531,11 @@ weak_extern (__pthread_key_create) weak_extern (__pthread_setspecific) weak_extern (__pthread_getspecific) weak_extern (__pthread_once) -weak_extern (__pthread_initialize) weak_extern (__pthread_atfork) +#ifdef SHARED weak_extern (_pthread_cleanup_push_defer) weak_extern (_pthread_cleanup_pop_restore) +#endif weak_extern (pthread_setcancelstate) # else # pragma weak __pthread_mutex_init @@ -552,7 +556,6 @@ weak_extern (pthread_setcancelstate) # pragma weak __pthread_setspecific # pragma weak __pthread_getspecific # pragma weak __pthread_once -# pragma weak __pthread_initialize # pragma weak __pthread_atfork # pragma weak _pthread_cleanup_push_defer # pragma weak _pthread_cleanup_pop_restore diff --git a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h index 0caf40d7b..cd64bc37e 100644 --- a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h +++ b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h @@ -20,6 +20,7 @@ #ifndef _BITS_STDIO_LOCK_H #define _BITS_STDIO_LOCK_H 1 +#include <bits/libc-lock.h> #include <lowlevellock.h> diff --git a/libpthread/nptl/sysdeps/pthread/pthread.h b/libpthread/nptl/sysdeps/pthread/pthread.h index 9090b30d9..bb322af8f 100644 --- a/libpthread/nptl/sysdeps/pthread/pthread.h +++ b/libpthread/nptl/sysdeps/pthread/pthread.h @@ -26,7 +26,7 @@ #define __need_sigset_t #include <signal.h> #include <bits/pthreadtypes.h> -#include <setjmp.h> +#include <bits/setjmp.h> #include <bits/wordsize.h> #if defined _LIBC && ( defined IS_IN_libc || defined NOT_IN_libc ) #include <bits/uClibc_pthread.h> @@ -536,6 +536,9 @@ class __pthread_cleanup_class needed or fall back on the copy which must exist somewhere else. */ extern __inline void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame); + +extern __inline void __pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) { if (__frame->__do_it) diff --git a/libpthread/nptl/sysdeps/pthread/sigaction.c b/libpthread/nptl/sysdeps/pthread/sigaction.c index 17443654d..54b5d2de4 100644 --- a/libpthread/nptl/sysdeps/pthread/sigaction.c +++ b/libpthread/nptl/sysdeps/pthread/sigaction.c @@ -31,6 +31,9 @@ # include <sigaction.c> int +sigaction (int sig, const struct sigaction *act, struct sigaction *oact); + +int __sigaction (int sig, const struct sigaction *act, struct sigaction *oact) { if (__builtin_expect (sig == SIGCANCEL || sig == SIGSETXID, 0)) @@ -41,9 +44,9 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact) return __libc_sigaction (sig, act, oact); } -libc_hidden_weak (__sigaction) +libc_hidden_proto(sigaction) weak_alias (__sigaction, sigaction) - +libc_hidden_weak(sigaction) #else # include_next <sigaction.c> diff --git a/libpthread/nptl/sysdeps/pthread/unwind-resume.c b/libpthread/nptl/sysdeps/pthread/unwind-resume.c index 594296723..018d2fd2f 100644 --- a/libpthread/nptl/sysdeps/pthread/unwind-resume.c +++ b/libpthread/nptl/sysdeps/pthread/unwind-resume.c @@ -27,13 +27,16 @@ static _Unwind_Reason_Code (*libgcc_s_personality) (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, struct _Unwind_Context *); +extern +void abort(void); + static void init (void) { void *resume = NULL; void *personality = NULL; void *handle; - + resume = personality = NULL; /* make gcc silent */ handle = dlopen ("libgcc_s.so.1", (RTLD_LOCAL | RTLD_LAZY)); if (handle == NULL diff --git a/libpthread/nptl/sysdeps/unix/sysdep.h b/libpthread/nptl/sysdeps/unix/sysdep.h new file mode 100644 index 000000000..3f5d1721c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysdep.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 92, 93, 96, 98, 2003 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 + 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. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdeps/generic/sysdep.h> + +#include <sys/syscall.h> +#define HAVE_SYSCALLS + +/* Note that using a `PASTE' macro loses. */ +#ifdef __STDC__ +#define SYSCALL__(name, args) PSEUDO (__##name, name, args) +#else +#define SYSCALL__(name, args) PSEUDO (__/**/name, name, args) +#endif +#define SYSCALL(name, args) PSEUDO (name, name, args) + +/* Machine-dependent sysdep.h files are expected to define the macro + PSEUDO (function_name, syscall_name) to emit assembly code to define the + C-callable function FUNCTION_NAME to do system call SYSCALL_NAME. + r0 and r1 are the system call outputs. MOVE(x, y) should be defined as + an instruction such that "MOVE(r1, r0)" works. ret should be defined + as the return instruction. */ + +#ifndef SYS_ify +#ifdef __STDC__ +#define SYS_ify(syscall_name) SYS_##syscall_name +#else +#define SYS_ify(syscall_name) SYS_/**/syscall_name +#endif +#endif + +/* Terminate a system call named SYM. This is used on some platforms + to generate correct debugging information. */ +#ifndef PSEUDO_END +#define PSEUDO_END(sym) +#endif +#ifndef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(sym) PSEUDO_END(sym) +#endif +#ifndef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(sym) PSEUDO_END(sym) +#endif + +/* Wrappers around system calls should normally inline the system call code. + But sometimes it is not possible or implemented and we use this code. */ +#define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in index 0c73e61c2..9826a3de4 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in @@ -5,34 +5,28 @@ # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # -libpthread_CSRC := pt-raise.c pthread_attr_getaffinity.c \ - pthread_attr_setaffinity.c pthread_getaffinity.c \ - pthread_getcpuclockid.c pthread_kill.c \ - pthread_mutex_cond_lock.c pthread_setaffinity.c \ - pthread_yield.c sem_post.c sem_timedwait.c \ - sem_trywait.c sem_wait.c pt-fork.c \ - sigtimedwait.c sigwaitinfo.c pt-sigwait.c pt-sleep.c \ - pt-msgsnd.c pt-msgrcv.c pt-waitpid.c pt-wait.c \ - pt-open64.c pt-tcdrain.c pt-fcntl.c pt-pread_pwrite.c \ - pt-llseek.c pt-fsync.c - -libpthread_SSRC := pt-close.S pt-open.S pt-read.S pt-write.S \ - pt-nanosleep.S pt-pause.S pt-lseek.S pt-accept.S \ - pt-connect.S pt-recv.S pt-recvfrom.S pt-recvmsg.S \ - pt-send.S pt-sendmsg.S pt-sendto.S - -libc_CSRC := libc_pthread_init.c libc_multiple_threads.c \ - register-atfork.c unregister-atfork.c getpid.c \ - raise.c sleep.c - -libc_SSRC := exit-thread.S close.S open.S read.S write.S nanosleep.S \ - creat.S pause.S msync.S lseek.S accept.S connect.S recv.S \ - recvfrom.S recvmsg.S send.S sendmsg.S sendto.S +libpthread_CSRC = pthread_attr_getaffinity.c \ + pthread_attr_setaffinity.c pthread_getaffinity.c \ + pthread_getcpuclockid.c pthread_kill.c \ + pthread_mutex_cond_lock.c pthread_setaffinity.c \ + pthread_yield.c sem_post.c sem_timedwait.c \ + sem_trywait.c sem_wait.c pt-fork.c \ + sigtimedwait.c sigwaitinfo.c sigwait.c pt-sleep.c + +libpthread_SSRC = #ptw-close.S ptw-open.S ptw-waitid.S ptw-waidpid.S ptw-write.S + +libc_CSRC = libc_pthread_init.c libc_multiple_threads.c \ + register-atfork.c unregister-atfork.c getpid.c \ + raise.c sleep.c jmp-unwind.c + +# These provide both a cancellable and a not cancellable implementation +libc_SSRC = close.S open.S waitpid.S write.S read.S librt_CSRC := mq_notify.c timer_create.c timer_delete.c \ timer_getoverr.c timer_gettime.c timer_routines.c \ timer_settime.c + ifeq ($(TARGET_ARCH),alpha) libpthread_CSRC += lowlevellock.c libc_CSRC += libc-lowlevellock.c @@ -56,6 +50,12 @@ libc_CSRC += libc-lowlevellock.c librt_CSRC := mq_notify.c endif +ifeq ($(TARGET_ARCH),sh) +SH_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(SH_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +endif + + ifeq ($(TARGET_ARCH),x86_64) librt_CSRC := mq_notify.c endif @@ -82,24 +82,13 @@ CFLAGS-OMIT-getpid.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 CFLAGS-OMIT-raise.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 CFLAGS-OMIT-sleep.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-exit-thread.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + CFLAGS-OMIT-close.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 CFLAGS-OMIT-open.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 CFLAGS-OMIT-read.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 CFLAGS-OMIT-write.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-nanosleep.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-creat.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-pause.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-accept.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-connect.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-recv.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-recvfrom.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-recvmsg.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-send.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-sendmsg.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-sendto.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-lseek.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -CFLAGS-OMIT-msync.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-waitpid.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + CFLAGS-OMIT-mq_notify.c = -DIS_IN_libpthread=1 CFLAGS-OMIT-timer_create.c = -DIS_IN_libpthread=1 CFLAGS-OMIT-timer_delete.c = -DIS_IN_libpthread=1 @@ -116,8 +105,15 @@ PTHREAD_LINUX_OBJ += $(patsubst %.S,$(PTHREAD_LINUX_OUT)/%.o,$(libpthread_SSRC)) libpthread-a-y += $(PTHREAD_LINUX_OBJ) libpthread-so-y += $(PTHREAD_LINUX_OBJ:.o=.oS) +libpthread-so-y += $(PTHREAD_LINUX_OUT)/pt-raise.oS libpthread-nomulti-y += $(PTHREAD_LINUX_OBJ) +ASFLAGS-open.S = -D_LIBC_REENTRANT +ASFLAGS-close.S = -D_LIBC_REENTRANT +ASFLAGS-read.S = -D_LIBC_REENTRANT +ASFLAGS-write.S = -D_LIBC_REENTRANT +ASFLAGS-waitpid.S = -D_LIBC_REENTRANT + LIBC_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(libc_CSRC)) LIBC_LINUX_OBJ += $(patsubst %.S,$(PTHREAD_LINUX_OUT)/%.o,$(libc_SSRC)) @@ -177,11 +173,16 @@ $(PTHREAD_LINUX_OUT)/lowlevelrwlock.h: $(PTHREAD_LINUX_OUT)/lowlevelrwlock.s $(PTHREAD_LINUX_OUT)/unwindbuf.h: $(PTHREAD_LINUX_OUT)/unwindbuf.s @sed -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ +$(PTHREAD_LINUX_DIR)/pt-sleep.c: + $(LN) -s sleep.c $@ + nptl_linux_headers: $(MAKE) $(PTHREAD_LINUX_OUT)/lowlevelbarrier.h $(MAKE) $(PTHREAD_LINUX_OUT)/lowlevelcond.h $(MAKE) $(PTHREAD_LINUX_OUT)/lowlevelrwlock.h $(MAKE) $(PTHREAD_LINUX_OUT)/unwindbuf.h + +nptl_linux_headers_bootstrap: $(LN) -sf ../../$(PTHREAD_LINUX_DIR)/bits/local_lim.h $(top_builddir)include/bits nptl_linux_headers_clean: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/close.S b/libpthread/nptl/sysdeps/unix/sysv/linux/close.S index b1cd59469..cf50a1eae 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/close.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/close.S @@ -1,9 +1,21 @@ #include <sysdep-cancel.h> + +/* +extern int __close_nocancel (int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + PSEUDO (__libc_close, close, 1) ret -PSEUDO_END (__libc_close) +PSEUDO_END(__libc_close) + +libc_hidden_def (__close_nocancel) libc_hidden_def (__libc_close) weak_alias (__libc_close, __close) libc_hidden_weak (__close) weak_alias (__libc_close, close) libc_hidden_weak (close) + + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c index 5d894225a..f8a64c0cb 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c @@ -227,6 +227,7 @@ pid_t __libc_fork (void) return pid; } +weak_alias(__libc_fork,__fork) libc_hidden_proto(fork) weak_alias(__libc_fork,fork) libc_hidden_weak(fork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/open.S b/libpthread/nptl/sysdeps/unix/sysv/linux/open.S index 50e4bcef0..486686a22 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/open.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/open.S @@ -1,9 +1,21 @@ #include <sysdep-cancel.h> + +/* +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + PSEUDO (__libc_open, open, 3) ret -PSEUDO_END (__libc_open) +PSEUDO_END(__libc_open) + +libc_hidden_def (__open_nocancel) libc_hidden_def (__libc_open) weak_alias (__libc_open, __open) libc_hidden_weak (__open) weak_alias (__libc_open, open) libc_hidden_weak (open) + + + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/read.S b/libpthread/nptl/sysdeps/unix/sysv/linux/read.S index dc63d1763..d3adfa84c 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/read.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/read.S @@ -1,9 +1,19 @@ #include <sysdep-cancel.h> + +/* +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + PSEUDO (__libc_read, read, 3) ret -PSEUDO_END (__libc_read) +PSEUDO_END(__libc_read) + +libc_hidden_def (__read_nocancel) libc_hidden_def (__libc_read) weak_alias (__libc_read, __read) libc_hidden_weak (__read) weak_alias (__libc_read, read) libc_hidden_weak (read) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 000000000..bde0a9292 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include "../../../../../../libc/signal/sigwait.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S b/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S new file mode 100644 index 000000000..f55d34629 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__waitpid, waitpid, 3) +ret +PSEUDO_END(__waitpid) + +libc_hidden_def (__waitpid) +weak_alias (__waitpid, waitpid) +libc_hidden_weak (waitpid) +weak_alias (__waitpid, __libc_waitpid) +libc_hidden_weak (__libc_waitpid) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/write.S b/libpthread/nptl/sysdeps/unix/sysv/linux/write.S index 168eab95c..43de3320d 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/write.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/write.S @@ -1,9 +1,19 @@ #include <sysdep-cancel.h> + +/* +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + PSEUDO (__libc_write, write, 3) ret -PSEUDO_END (__libc_write) +PSEUDO_END(__libc_write) + +libc_hidden_def (__write_nocancel) libc_hidden_def (__libc_write) weak_alias (__libc_write, __write) libc_hidden_weak (__write) weak_alias (__libc_write, write) libc_hidden_weak (write) + +#endif diff --git a/libpthread/nptl_db/structs.def b/libpthread/nptl_db/structs.def index b17a628e0..823af5cba 100644 --- a/libpthread/nptl_db/structs.def +++ b/libpthread/nptl_db/structs.def @@ -1,5 +1,5 @@ /* List of types and symbols in libpthread examined by libthread_db. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2006 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 @@ -74,6 +74,8 @@ DB_STRUCT_FIELD (link_map, l_tls_modid) #if !defined IS_IN_libpthread || USE_TLS DB_STRUCT_ARRAY_FIELD (dtv, dtv) +# define pointer_val pointer.val /* Field of anonymous struct in dtv_t. */ +DB_STRUCT_FIELD (dtv_t, pointer_val) #endif #if !defined IS_IN_libpthread || TLS_TCB_AT_TP DB_STRUCT_FIELD (pthread, dtvp) diff --git a/libpthread/nptl_db/td_thr_tlsbase.c b/libpthread/nptl_db/td_thr_tlsbase.c index c57009a73..aaeda6f3c 100644 --- a/libpthread/nptl_db/td_thr_tlsbase.c +++ b/libpthread/nptl_db/td_thr_tlsbase.c @@ -1,5 +1,5 @@ /* Locate TLS data for a thread. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2006 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 @@ -25,7 +25,7 @@ td_thr_tlsbase (const td_thrhandle_t *th, psaddr_t *base) { td_err_e err; - psaddr_t dtv, dtvptr; + psaddr_t dtv, dtvslot, dtvptr; if (modid < 1) return TD_NOTLS; @@ -35,8 +35,13 @@ td_thr_tlsbase (const td_thrhandle_t *th, if (err != TD_OK) return err; - /* Get the corresponding entry in the DTV. */ - err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtv, dtv, dtv, modid); + /* Find the corresponding entry in the DTV. */ + err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid); + if (err != TD_OK) + return err; + + /* Extract the TLS block address from that DTV slot. */ + err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0); if (err != TD_OK) return err; |