diff options
50 files changed, 536 insertions, 297 deletions
@@ -1,9 +1,7 @@ -Subject: [PATCH] getcontext, makecontext, setcontext, swapcontext +From: Thomas Schwinge <thomas@schwinge.name> +Subject: [PATCH] tls-threadvar -From: Thomas Schwinge <thomas@codesourcery.com> +replace the custom threadvar mechanism with generic TLS. +That will fix sigaltstack. -Adapted from the Linux x86 functions. - -Not thoroughly tested, but manual testing as well as glibc tests look fine, and -manual -lpthread testing also looks fine (within the given bounds for a new -stack to be used with makecontext). +Note: the added reply_port and _hurd_sigstate fields should be kept last. @@ -515,6 +515,15 @@ $(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules PROVIDE(__start__hurd_fork_parent_hook = .);\ _hurd_fork_parent_hook : { *(_hurd_fork_parent_hook) }\ PROVIDE(__stop__hurd_fork_parent_hook = .);\ + PROVIDE(__start__hurd_atfork_prepare_hook = .);\ + _hurd_atfork_prepare_hook : { *(_hurd_atfork_prepare_hook) }\ + PROVIDE(__stop__hurd_atfork_prepare_hook = .);\ + PROVIDE(__start__hurd_atfork_child_hook = .);\ + _hurd_atfork_child_hook : { *(_hurd_atfork_child_hook) }\ + PROVIDE(__stop__hurd_atfork_child_hook = .);\ + PROVIDE(__start__hurd_atfork_parent_hook = .);\ + _hurd_atfork_parent_hook : { *(_hurd_atfork_parent_hook) }\ + PROVIDE(__stop__hurd_atfork_parent_hook = .);\ PROVIDE(__start__hurd_fork_locks = .);\ _hurd_fork_locks : { *(_hurd_fork_locks) }\ PROVIDE(__stop__hurd_fork_locks = .);\ diff --git a/Versions.def b/Versions.def index d834b10479..d7982bf636 100644 --- a/Versions.def +++ b/Versions.def @@ -105,6 +105,7 @@ libpthread { GLIBC_2.6 GLIBC_2.11 GLIBC_2.12 + GLIBC_2.17 GLIBC_2.18 GLIBC_PRIVATE } diff --git a/hurd/Versions b/hurd/Versions index ec405db86a..74df5298a6 100644 --- a/hurd/Versions +++ b/hurd/Versions @@ -25,20 +25,16 @@ libc { # weak refs to libthreads functions that libc calls iff libthreads in use cthread_fork; cthread_detach; + pthread_getattr_np; pthread_attr_getstack; %endif # necessary for the Hurd brk implementation _end; # variables used in macros & inline functions - __hurd_sigthread_stack_base; __hurd_sigthread_stack_end; - __hurd_sigthread_variables; __hurd_threadvar_max; __hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset; - # functions used in macros & inline functions - __hurd_errno_location; - # functions used in libmachuser and libhurduser _S_catch_exception_raise; _S_catch_exception_raise_state; @@ -169,6 +165,7 @@ libc { HURD_CTHREADS_0.3 { # weak refs to libthreads functions that libc calls iff libthreads in use cthread_fork; cthread_detach; + pthread_getattr_np; pthread_attr_getstack; # variables used for detecting cthreads _cthread_exit_routine; _cthread_init_routine; diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h index 5776e21e8b..eaaa332050 100644 --- a/hurd/hurd/fd.h +++ b/hurd/hurd/fd.h @@ -60,7 +60,7 @@ extern struct mutex _hurd_dtable_lock; /* Locks those two variables. */ struct hurd_fd *_hurd_fd_get (int fd); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_FD_H_EXTERN_INLINE struct hurd_fd * _hurd_fd_get (int fd) { diff --git a/hurd/hurd/port.h b/hurd/hurd/port.h index eaf380d6eb..810bb3171a 100644 --- a/hurd/hurd/port.h +++ b/hurd/hurd/port.h @@ -62,7 +62,7 @@ struct hurd_port void _hurd_port_init (struct hurd_port *port, mach_port_t init); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_PORT_H_EXTERN_INLINE void _hurd_port_init (struct hurd_port *port, mach_port_t init) { @@ -83,7 +83,7 @@ mach_port_t _hurd_port_locked_get (struct hurd_port *port, struct hurd_userlink *link); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_PORT_H_EXTERN_INLINE mach_port_t _hurd_port_locked_get (struct hurd_port *port, struct hurd_userlink *link) @@ -107,7 +107,7 @@ mach_port_t _hurd_port_get (struct hurd_port *port, struct hurd_userlink *link); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_PORT_H_EXTERN_INLINE mach_port_t _hurd_port_get (struct hurd_port *port, struct hurd_userlink *link) @@ -129,7 +129,7 @@ _hurd_port_free (struct hurd_port *port, struct hurd_userlink *link, mach_port_t used_port); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_PORT_H_EXTERN_INLINE void _hurd_port_free (struct hurd_port *port, struct hurd_userlink *link, @@ -157,7 +157,7 @@ _hurd_port_free (struct hurd_port *port, void _hurd_port_locked_set (struct hurd_port *port, mach_port_t newport); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_PORT_H_EXTERN_INLINE void _hurd_port_locked_set (struct hurd_port *port, mach_port_t newport) { @@ -174,7 +174,7 @@ _hurd_port_locked_set (struct hurd_port *port, mach_port_t newport) void _hurd_port_set (struct hurd_port *port, mach_port_t newport); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_PORT_H_EXTERN_INLINE void _hurd_port_set (struct hurd_port *port, mach_port_t newport) { diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index 796761eba4..8d63d2d0c0 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -40,7 +40,6 @@ #include <cthreads.h> /* For `struct mutex'. */ #include <setjmp.h> /* For `jmp_buf'. */ #include <spin-lock.h> -#include <hurd/threadvar.h> /* We cache sigstate in a threadvar. */ struct hurd_signal_preemptor; /* <hurd/sigpreempt.h> */ @@ -64,7 +63,9 @@ struct hurd_sigstate spin_lock_t lock; /* Locks most of the rest of the structure. */ + /* The signal state holds a reference on the thread port. */ thread_t thread; + struct hurd_sigstate *next; /* Linked-list of thread sigstates. */ sigset_t blocked; /* What signals are blocked. */ @@ -118,7 +119,9 @@ extern struct hurd_sigstate *_hurd_sigstates; extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates. */ -/* Get the sigstate of a given thread, taking its lock. */ +/* Get the sigstate of a given thread. If there was no sigstate for + the thread, one is created, and the thread gains a reference. If + the given thread is MACH_PORT_NULL, return the global sigstate. */ extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t); @@ -155,14 +158,17 @@ extern void _hurd_sigstate_delete (thread_t thread); #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline #endif -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { - struct hurd_sigstate **location = (struct hurd_sigstate **) - (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); + struct hurd_sigstate **location = &THREAD_SELF->_hurd_sigstate; if (*location == NULL) - *location = _hurd_thread_sigstate (__mach_thread_self ()); + { + thread_t self = __mach_thread_self (); + *location = _hurd_thread_sigstate (self); + __mach_port_deallocate (__mach_task_self (), self); + } return *location; } #endif @@ -188,21 +194,37 @@ extern int _hurd_core_limit; void *_hurd_critical_section_lock (void); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_SIGNAL_H_EXTERN_INLINE void * _hurd_critical_section_lock (void) { - struct hurd_sigstate **location = (struct hurd_sigstate **) - (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); - struct hurd_sigstate *ss = *location; + struct hurd_sigstate **location; + struct hurd_sigstate *ss; + +#ifdef __LIBC_NO_TLS + if (__LIBC_NO_TLS()) + /* TLS is currently initializing, no need to enter critical section. */ + return NULL; +#endif + + location = &THREAD_SELF->_hurd_sigstate; + ss = *location; if (ss == NULL) { + thread_t self = __mach_thread_self (); + /* The thread variable is unset; this must be the first time we've asked for it. In this case, the critical section flag cannot possible already be set. Look up our sigstate structure the slow +<<<<<<< HEAD + way. */ + ss = THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (self); + __mach_port_deallocate (__mach_task_self (), self); +======= way; this locks the sigstate lock. */ ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); __spin_unlock (&ss->lock); +>>>>>>> t/tls-threadvar } if (! __spin_try_lock (&ss->critical_section_lock)) @@ -218,7 +240,7 @@ _hurd_critical_section_lock (void) void _hurd_critical_section_unlock (void *our_lock); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_SIGNAL_H_EXTERN_INLINE void _hurd_critical_section_unlock (void *our_lock) { diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h index ebfce35b51..888d5354e9 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -20,6 +20,7 @@ #define _HURD_THREADVAR_H #include <features.h> +#include <tls.h> /* The per-thread variables are found by ANDing this mask with the value of the stack pointer and then adding this offset. @@ -30,92 +31,24 @@ __hurd_threadvar_stack_offset to a small offset that skips the data cthreads itself maintains at the base of each thread's stack. - In the single-threaded case, __hurd_threadvar_stack_mask is zero, so the - stack pointer is ignored; and __hurd_threadvar_stack_offset gives the - address of a small allocated region which contains the variables for the - single thread. */ + In the single-threaded or libpthread case, __hurd_threadvar_stack_mask is + zero, so the stack pointer is ignored. */ extern unsigned long int __hurd_threadvar_stack_mask; extern unsigned long int __hurd_threadvar_stack_offset; -/* A special case must always be made for the signal thread. Even when there - is only one user thread and an allocated region can be used for the user - thread's variables, the signal thread needs to have its own location for - per-thread variables. The variables __hurd_sigthread_stack_base and +/* The variables __hurd_sigthread_stack_base and __hurd_sigthread_stack_end define the bounds of the stack used by the signal thread, so that thread can always be specifically identified. */ extern unsigned long int __hurd_sigthread_stack_base; extern unsigned long int __hurd_sigthread_stack_end; -extern unsigned long int *__hurd_sigthread_variables; -/* At the location described by the two variables above, - there are __hurd_threadvar_max `unsigned long int's of per-thread data. */ +/* We do not use threadvars any more, this is kept as zero for compatibility with cthreads */ extern unsigned int __hurd_threadvar_max; -/* These values are the indices for the standard per-thread variables. */ -enum __hurd_threadvar_index - { - _HURD_THREADVAR_MIG_REPLY, /* Reply port for MiG user stub functions. */ - _HURD_THREADVAR_ERRNO, /* `errno' value for this thread. */ - _HURD_THREADVAR_SIGSTATE, /* This thread's `struct hurd_sigstate'. */ - _HURD_THREADVAR_DYNAMIC_USER, /* Dynamically-assigned user variables. */ - _HURD_THREADVAR_MALLOC, /* For use of malloc. */ - _HURD_THREADVAR_DL_ERROR, /* For use of -ldl and dynamic linker. */ - _HURD_THREADVAR_RPC_VARS, /* For state of RPC functions. */ - _HURD_THREADVAR_LOCALE, /* For thread-local locale setting. */ - _HURD_THREADVAR_CTYPE_B, /* Cache of thread-local locale data. */ - _HURD_THREADVAR_CTYPE_TOLOWER, /* Cache of thread-local locale data. */ - _HURD_THREADVAR_CTYPE_TOUPPER, /* Cache of thread-local locale data. */ - _HURD_THREADVAR_MAX /* Default value for __hurd_threadvar_max. */ - }; - - -#ifndef _HURD_THREADVAR_H_EXTERN_INLINE -#define _HURD_THREADVAR_H_EXTERN_INLINE __extern_inline -#endif - -/* Return the location of the value for the per-thread variable with index - INDEX used by the thread whose stack pointer is SP. */ - -extern unsigned long int *__hurd_threadvar_location_from_sp - (enum __hurd_threadvar_index __index, void *__sp); - -#ifdef __USE_EXTERN_INLINES -_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * -__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, - void *__sp) -{ - unsigned long int __stack = (unsigned long int) __sp; - return &((__stack >= __hurd_sigthread_stack_base && - __stack < __hurd_sigthread_stack_end) - ? __hurd_sigthread_variables - : (unsigned long int *) ((__stack & __hurd_threadvar_stack_mask) + - __hurd_threadvar_stack_offset))[__index]; -} -#endif - -#include <machine-sp.h> /* Define __thread_stack_pointer. */ - -/* Return the location of the current thread's value for the - per-thread variable with index INDEX. */ - -extern unsigned long int * -__hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW - /* This declaration tells the compiler that the value is constant - given the same argument. We assume this won't be called twice from - the same stack frame by different threads. */ - __attribute__ ((__const__)); - -#ifdef __USE_EXTERN_INLINES -_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * -__hurd_threadvar_location (enum __hurd_threadvar_index __index) -{ - return __hurd_threadvar_location_from_sp (__index, - __thread_stack_pointer ()); -} -#endif - +extern mach_port_t __hurd_reply_port0; +#define __hurd_local_reply_port (*(__LIBC_NO_TLS() ? &__hurd_reply_port0 : &THREAD_SELF->reply_port)) #endif /* hurd/threadvar.h */ diff --git a/hurd/hurd/userlink.h b/hurd/hurd/userlink.h index c6286f30c5..bd0a8c2569 100644 --- a/hurd/hurd/userlink.h +++ b/hurd/hurd/userlink.h @@ -80,7 +80,7 @@ void _hurd_userlink_link (struct hurd_userlink **chainp, struct hurd_userlink *link); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_USERLINK_H_EXTERN_INLINE void _hurd_userlink_link (struct hurd_userlink **chainp, struct hurd_userlink *link) @@ -109,7 +109,7 @@ _hurd_userlink_link (struct hurd_userlink **chainp, int _hurd_userlink_unlink (struct hurd_userlink *link); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_USERLINK_H_EXTERN_INLINE int _hurd_userlink_unlink (struct hurd_userlink *link) { @@ -143,7 +143,7 @@ _hurd_userlink_unlink (struct hurd_userlink *link) int _hurd_userlink_clear (struct hurd_userlink **chainp); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_USERLINK_H_EXTERN_INLINE int _hurd_userlink_clear (struct hurd_userlink **chainp) { diff --git a/hurd/hurdexec.c b/hurd/hurdexec.c index 77bf833742..eb2d2bfc22 100644 --- a/hurd/hurdexec.c +++ b/hurd/hurdexec.c @@ -104,7 +104,6 @@ _hurd_exec (task_t task, file_t file, ss = _hurd_self_sigstate (); - assert (! __spin_lock_locked (&ss->critical_section_lock)); __spin_lock (&ss->critical_section_lock); _hurd_sigstate_lock (ss); diff --git a/hurd/hurdselect.c b/hurd/hurdselect.c index 7bbf74f460..d104be07dc 100644 --- a/hurd/hurdselect.c +++ b/hurd/hurdselect.c @@ -464,13 +464,6 @@ _hurd_select (int nfds, } } - if (err == MACH_RCV_TIMED_OUT) - /* This is the normal value for ERR. We might have timed out and - read no messages. Otherwise, after receiving the first message, - we poll for more messages. We receive with a timeout of 0 to - effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no - message waiting. */ - err = 0; if (msgerr == MACH_RCV_INTERRUPTED) /* Interruption on our side (e.g. signal reception). */ err = EINTR; @@ -551,7 +544,15 @@ _hurd_select (int nfds, readiness of the erring object and the next call hopefully will get the error again. */ if (type & SELECT_ERROR) - type = SELECT_ALL; + { + type = 0; + if (readfds != NULL && FD_ISSET (i, readfds)) + type |= SELECT_READ; + if (writefds != NULL && FD_ISSET (i, writefds)) + type |= SELECT_WRITE; + if (exceptfds != NULL && FD_ISSET (i, exceptfds)) + type |= SELECT_URG; + } if (type & SELECT_READ) ready++; diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 12ea82955b..a69b87df0b 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -20,6 +20,7 @@ #include <string.h> #include <cthreads.h> /* For `struct mutex'. */ +#include <pthread.h> #include <mach.h> #include <mach/thread_switch.h> @@ -45,7 +46,6 @@ thread_t _hurd_msgport_thread; /* These are set up by _hurdsig_init. */ unsigned long int __hurd_sigthread_stack_base; unsigned long int __hurd_sigthread_stack_end; -unsigned long int *__hurd_sigthread_variables; /* Linked-list of per-thread signal state. */ struct hurd_sigstate *_hurd_sigstates; @@ -105,6 +105,8 @@ _hurd_thread_sigstate (thread_t thread) } else { + error_t err; + /* Use the global actions as a default for new threads. */ struct hurd_sigstate *s = _hurd_global_sigstate; if (s) @@ -118,6 +120,11 @@ _hurd_thread_sigstate (thread_t thread) ss->next = _hurd_sigstates; _hurd_sigstates = ss; + + err = __mach_port_mod_refs (__mach_task_self (), thread, + MACH_PORT_RIGHT_SEND, 1); + if (err) + __libc_fatal ("hurd: Can't add reference on Mach thread\n"); } } __mutex_unlock (&_hurd_siglock); @@ -125,8 +132,7 @@ _hurd_thread_sigstate (thread_t thread) } /* Destroy a sigstate structure. Called by libpthread just before the - * corresponding thread is terminated (the kernel thread port must remain valid - * until this function is called.) */ + * corresponding thread is terminated. */ void _hurd_sigstate_delete (thread_t thread) { @@ -143,7 +149,12 @@ _hurd_sigstate_delete (thread_t thread) __mutex_unlock (&_hurd_siglock); if (ss) - free (ss); + { + if (ss->thread != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), ss->thread); + + free (ss); + } } /* Make SS a global receiver, with pthread signal semantics. */ @@ -334,11 +345,11 @@ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state, that this location can be set without faulting, or else return NULL. */ static mach_port_t * -interrupted_reply_port_location (struct machine_thread_all_state *thread_state, +interrupted_reply_port_location (thread_t thread, + struct machine_thread_all_state *thread_state, int sigthread) { - mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp - (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP); + mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port; if (sigthread && _hurdsig_catch_memory_fault (portloc)) /* Faulted trying to read the stack. */ @@ -423,7 +434,8 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread, our nonzero return tells the trampoline code to finish the message receive operation before running the handler. */ - mach_port_t *reply = interrupted_reply_port_location (state, + mach_port_t *reply = interrupted_reply_port_location (ss->thread, + state, sigthread); error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout); @@ -980,7 +992,8 @@ post_signal (struct hurd_sigstate *ss, if (! machine_get_basic_state (ss->thread, &thread_state)) goto sigbomb; - loc = interrupted_reply_port_location (&thread_state, 1); + loc = interrupted_reply_port_location (ss->thread, + &thread_state, 1); if (loc && *loc != MACH_PORT_NULL) /* This is the reply port for the context which called sigreturn. Since we are abandoning that context entirely @@ -1046,7 +1059,8 @@ post_signal (struct hurd_sigstate *ss, { /* Fetch the thread variable for the MiG reply port, and set it to MACH_PORT_NULL. */ - mach_port_t *loc = interrupted_reply_port_location (&thread_state, + mach_port_t *loc = interrupted_reply_port_location (ss->thread, + &thread_state, 1); if (loc) { @@ -1452,7 +1466,11 @@ _hurdsig_init (const int *intarray, size_t intarraysize) /* Start the signal thread listening on the message port. */ - if (__hurd_threadvar_stack_mask == 0) +#pragma weak cthread_fork +#pragma weak cthread_detach +#pragma weak pthread_getattr_np +#pragma weak pthread_attr_getstack + if (!cthread_fork) { err = __thread_create (__mach_task_self (), &_hurd_msgport_thread); assert_perror (err); @@ -1467,12 +1485,6 @@ _hurdsig_init (const int *intarray, size_t intarraysize) assert_perror (err); __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize; - __hurd_sigthread_variables = - malloc (__hurd_threadvar_max * sizeof (unsigned long int)); - if (__hurd_sigthread_variables == NULL) - __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n"); - memset (__hurd_sigthread_variables, 0, - __hurd_threadvar_max * sizeof (unsigned long int)); /* Reinitialize the MiG support routines so they will use a per-thread variable for the cached reply port. */ @@ -1483,6 +1495,7 @@ _hurdsig_init (const int *intarray, size_t intarraysize) } else { + cthread_t thread; /* When cthreads is being used, we need to make the signal thread a proper cthread. Otherwise it cannot use mutex_lock et al, which will be the cthreads versions. Various of the message port RPC @@ -1492,9 +1505,20 @@ _hurdsig_init (const int *intarray, size_t intarraysize) we'll let the signal thread's per-thread variables be found as for any normal cthread, and just leave the magic __hurd_sigthread_* values all zero so they'll be ignored. */ -#pragma weak cthread_fork -#pragma weak cthread_detach - cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0)); + cthread_detach (thread = cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0)); + + if (pthread_getattr_np) + { + /* Record stack layout for fork() */ + pthread_attr_t attr; + void *addr; + size_t size; + + pthread_getattr_np ((pthread_t) thread, &attr); + pthread_attr_getstack (&attr, &addr, &size); + __hurd_sigthread_stack_base = (uintptr_t) addr; + __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size; + } /* XXX We need the thread port for the signal thread further on in this thread (see hurdfault.c:_hurdsigfault_init). diff --git a/hurd/hurdstartup.c b/hurd/hurdstartup.c index 38147c94ea..688772ad35 100644 --- a/hurd/hurdstartup.c +++ b/hurd/hurdstartup.c @@ -23,7 +23,6 @@ #include <hurd.h> #include <hurd/exec_startup.h> #include <sysdep.h> -#include <hurd/threadvar.h> #include <unistd.h> #include <elf.h> #include <set-hooks.h> diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c index de966aa09b..a1819a2b36 100644 --- a/hurd/sigunwind.c +++ b/hurd/sigunwind.c @@ -18,6 +18,7 @@ #include <hurd.h> #include <thread_state.h> +#include <hurd/threadvar.h> #include <jmpbuf-unwind.h> #include <assert.h> #include <stdint.h> @@ -38,8 +39,7 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val) { /* Destroy the MiG reply port used by the signal handler, and restore the reply port in use by the thread when interrupted. */ - mach_port_t *reply_port = - (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); + mach_port_t *reply_port = &__hurd_local_reply_port; if (*reply_port) { mach_port_t port = *reply_port; diff --git a/hurd/thread-cancel.c b/hurd/thread-cancel.c index 2e8d91e7ba..eaf3d9e342 100644 --- a/hurd/thread-cancel.c +++ b/hurd/thread-cancel.c @@ -90,7 +90,6 @@ hurd_check_cancel (void) int cancel; __spin_lock (&ss->lock); - assert (! __spin_lock_locked (&ss->critical_section_lock)); cancel = ss->cancel; ss->cancel = 0; __spin_unlock (&ss->lock); diff --git a/include/errno.h b/include/errno.h index effa593a27..5b75ffc051 100644 --- a/include/errno.h +++ b/include/errno.h @@ -21,7 +21,7 @@ extern int rtld_errno attribute_hidden; # include <tls.h> -# if !defined(__GNU__) +# if !(defined(__GNU__) && defined IS_IN_rtld) # undef errno # ifndef NOT_IN_libc # define errno __libc_errno diff --git a/misc/chflags.c b/misc/chflags.c index 3785c6b7b0..cf3b77fdf0 100644 --- a/misc/chflags.c +++ b/misc/chflags.c @@ -21,12 +21,12 @@ /* Change the flags of FILE to FLAGS. */ -int chflags (const char *file, int flags) __THROW; +int chflags (const char *file, unsigned long int flags) __THROW; int chflags (file, flags) const char *file; - int flags; + unsigned long int flags; { if (file == NULL) { diff --git a/misc/fchflags.c b/misc/fchflags.c index 53805eaf0e..1e61921aac 100644 --- a/misc/fchflags.c +++ b/misc/fchflags.c @@ -21,12 +21,12 @@ /* Change the flags of the file referenced by FD to FLAGS. */ -int fchflags (int fd, int flags) __THROW; +int fchflags (int fd, unsigned long int flags) __THROW; int fchflags (fd, flags) int fd; - int flags; + unsigned long int flags; { if (fd < 0) { diff --git a/misc/sys/file.h b/misc/sys/file.h index 64e8764c47..a5892db17c 100644 --- a/misc/sys/file.h +++ b/misc/sys/file.h @@ -40,6 +40,7 @@ __BEGIN_DECLS #define LOCK_SH 1 /* Shared lock. */ #define LOCK_EX 2 /* Exclusive lock. */ #define LOCK_UN 8 /* Unlock. */ +#define __LOCK_ATOMIC 16 /* Atomic update. */ /* Can be OR'd in to one of the above. */ #define LOCK_NB 4 /* Don't block when locking. */ diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile index 7ff9a925c3..500589d353 100644 --- a/sysdeps/mach/hurd/Makefile +++ b/sysdeps/mach/hurd/Makefile @@ -167,6 +167,10 @@ $(objpfx)librtld.map: $(rpcuserlibs:.so=_pic.a) CFLAGS-dl-load.c = -DEXTERNAL_MAP_FROM_FD endif +ifeq ($(subdir),posix) +CFLAGS-confstr.c += -DLIBPTHREAD_VERSION='"libpthread 0.3"' +endif + # Override the generic Makeconfig values so we link against the RPC libs. link-libc-static := -Wl,--start-group \ $(patsubst %,$(common-objpfx)%.a,\ diff --git a/sysdeps/mach/hurd/Versions b/sysdeps/mach/hurd/Versions index 89e19061af..f760a80401 100644 --- a/sysdeps/mach/hurd/Versions +++ b/sysdeps/mach/hurd/Versions @@ -6,6 +6,7 @@ libc { GLIBC_PRIVATE { # Functions shared with the dynamic linker __libc_read; __libc_write; __libc_lseek64; + __libc_lock_self0; __libc_get_lock_self; _dl_init_first; } @@ -14,8 +15,6 @@ libc { ld { GLIBC_2.0 { # variables that must be shared with libc - __hurd_sigthread_stack_base; __hurd_sigthread_stack_end; - __hurd_sigthread_variables; __hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset; # functions that must be shared with libc @@ -33,5 +32,6 @@ ld { # functions that must be shared with libc __libc_read; __libc_write; __libc_lseek64; + __libc_lock_self0; __libc_get_lock_self; } } diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h index 9d598a1bf2..9460be7ff0 100644 --- a/sysdeps/mach/hurd/bits/fcntl.h +++ b/sysdeps/mach/hurd/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for GNU. - Copyright (C) 1993-2013 Free Software Foundation, Inc. + Copyright (C) 1993-2014 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 @@ -163,9 +163,18 @@ # define F_GETOWN 5 /* Get owner (receiver of SIGIO). */ # define F_SETOWN 6 /* Set owner (receiver of SIGIO). */ #endif -#define F_GETLK 7 /* Get record locking info. */ -#define F_SETLK 8 /* Set record locking info (non-blocking). */ -#define F_SETLKW 9 /* Set record locking info (blocking). */ +#ifdef __USE_FILE_OFFSET64 +# define F_GETLK F_GETLK64 +# define F_SETLK F_SETLK64 +# define F_SETLKW F_SETLKW64 +#else +# define F_GETLK 7 /* Get record locking info. */ +# define F_SETLK 8 /* Set record locking info (non-blocking). */ +# define F_SETLKW 9 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 10 /* Get record locking info. */ +#define F_SETLK64 11 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 12 /* Set record locking info (blocking). */ #ifdef __USE_XOPEN2K8 # define F_DUPFD_CLOEXEC 1030 /* Duplicate, set FD_CLOEXEC on new one. */ diff --git a/sysdeps/mach/hurd/bits/libc-lock.h b/sysdeps/mach/hurd/bits/libc-lock.h index 8bf5656f26..c53fe8729b 100644 --- a/sysdeps/mach/hurd/bits/libc-lock.h +++ b/sysdeps/mach/hurd/bits/libc-lock.h @@ -24,7 +24,6 @@ #include <tls.h> #endif #include <cthreads.h> -#include <hurd/threadvar.h> typedef struct mutex __libc_lock_t; typedef struct @@ -35,7 +34,12 @@ typedef struct } __libc_lock_recursive_t; typedef __libc_lock_recursive_t __rtld_lock_recursive_t; -#define __libc_lock_owner_self() ((void *) __hurd_threadvar_location (0)) +extern char __libc_lock_self0[0]; +/* We have to hide the __libc_lock_self access behind a function call, + otherwise gcc >= 4.9 would try to prefetch the TLS dereference even before + the __LIBC_NO_TLS test is finished... */ +extern void *__libc_get_lock_self(void); +#define __libc_lock_owner_self() (__LIBC_NO_TLS() ? &__libc_lock_self0 : __libc_get_lock_self()) #else typedef struct __libc_lock_opaque__ __libc_lock_t; diff --git a/sysdeps/mach/hurd/bits/posix_opt.h b/sysdeps/mach/hurd/bits/posix_opt.h index 028f6f1ab7..2585804ea5 100644 --- a/sysdeps/mach/hurd/bits/posix_opt.h +++ b/sysdeps/mach/hurd/bits/posix_opt.h @@ -71,24 +71,38 @@ /* XPG4.2 shared memory is supported. */ #define _XOPEN_SHM 1 -/* We do not have the POSIX threads interface. */ -#define _POSIX_THREADS -1 +/* Tell we have POSIX threads. */ +#define _POSIX_THREADS 200112L /* We have the reentrant functions described in POSIX. */ #define _POSIX_REENTRANT_FUNCTIONS 1 #define _POSIX_THREAD_SAFE_FUNCTIONS 200809L -/* These are all things that won't be supported when _POSIX_THREADS is not. */ +/* We do not provide priority scheduling for threads. */ #define _POSIX_THREAD_PRIORITY_SCHEDULING -1 -#define _POSIX_THREAD_ATTR_STACKSIZE -1 -#define _POSIX_THREAD_ATTR_STACKADDR -1 + +/* We support user-defined stack sizes. */ +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* We support user-defined stacks. */ +#define _POSIX_THREAD_ATTR_STACKADDR 200112L + +/* We do not support priority inheritence. */ #define _POSIX_THREAD_PRIO_INHERIT -1 + +/* We do not support priority protection. */ #define _POSIX_THREAD_PRIO_PROTECT -1 + #ifdef __USE_XOPEN2K8 +/* We do not support priority inheritence for robust mutexes. */ # define _POSIX_THREAD_ROBUST_PRIO_INHERIT -1 + +/* We do not support priority protection for robust mutexes. */ # define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1 #endif -#define _POSIX_SEMAPHORES -1 + +/* We support POSIX.1b semaphores. */ +#define _POSIX_SEMAPHORES 200112L /* Real-time signals are not yet supported. */ #define _POSIX_REALTIME_SIGNALS -1 @@ -121,17 +135,17 @@ /* GNU libc provides regular expression handling. */ #define _POSIX_REGEXP 1 -/* Reader/Writer locks are not available. */ -#define _POSIX_READER_WRITER_LOCKS -1 +/* Reader/Writer locks are available. */ +#define _POSIX_READER_WRITER_LOCKS 200112L /* We have a POSIX shell. */ #define _POSIX_SHELL 1 -/* We cannot support the Timeouts option without _POSIX_THREADS. */ -#define _POSIX_TIMEOUTS -1 +/* We support the Timeouts option. */ +#define _POSIX_TIMEOUTS 200112L -/* We do not support spinlocks. */ -#define _POSIX_SPIN_LOCKS -1 +/* We support spinlocks. */ +#define _POSIX_SPIN_LOCKS 200112L /* The `spawn' function family is supported. */ #define _POSIX_SPAWN 200809L @@ -139,8 +153,8 @@ /* We do not have POSIX timers, but could in future without ABI change. */ #define _POSIX_TIMERS 0 -/* The barrier functions are not available. */ -#define _POSIX_BARRIERS -1 +/* We support barrier functions. */ +#define _POSIX_BARRIERS 200112L /* POSIX message queues could be available in future. */ #define _POSIX_MESSAGE_PASSING 0 diff --git a/sysdeps/mach/hurd/bits/stat.h b/sysdeps/mach/hurd/bits/stat.h index be9defd385..7db702131d 100644 --- a/sysdeps/mach/hurd/bits/stat.h +++ b/sysdeps/mach/hurd/bits/stat.h @@ -222,9 +222,40 @@ struct stat64 S_IUSEUNK|S_IUNKNOWN|07777)) #endif -/* Default file creation mask (umask). */ #ifdef __USE_BSD + +/* Default file creation mask (umask). */ # define CMASK 0022 + + +/* Definitions of flags stored in file flags word. */ + +/* Super-user and owner changeable flags. */ +# define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags */ +# define UF_NODUMP 0x00000001 /* do not dump file */ +# define UF_IMMUTABLE 0x00000002 /* file may not be changed */ +# define UF_APPEND 0x00000004 /* writes to file may only append */ +# define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */ +# define UF_NOUNLINK 0x00000010 /* file may not be removed or renamed */ + +/* Super-user changeable flags. */ +# define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */ +# define SF_ARCHIVED 0x00010000 /* file is archived */ +# define SF_IMMUTABLE 0x00020000 /* file may not be changed */ +# define SF_APPEND 0x00040000 /* writes to file may only append */ +# define SF_NOUNLINK 0x00100000 /* file may not be removed or renamed */ +# define SF_SNAPSHOT 0x00200000 /* snapshot inode */ + +__BEGIN_DECLS + +/* Set file flags for FILE to FLAGS. */ +extern int chflags (__const char *__file, unsigned long int __flags) __THROW; + +/* Set file flags of the file referred to by FD to FLAGS. */ +extern int fchflags (int __fd, unsigned long int __flags) __THROW; + +__END_DECLS + #endif #endif /* bits/stat.h */ diff --git a/sysdeps/mach/hurd/chflags.c b/sysdeps/mach/hurd/chflags.c index 0f4614c8be..7ed7ed5d7e 100644 --- a/sysdeps/mach/hurd/chflags.c +++ b/sysdeps/mach/hurd/chflags.c @@ -24,7 +24,7 @@ /* XXX shouldn't this be __chflags? */ int -chflags (const char *file, int flags) +chflags (const char *file, unsigned long int flags) { error_t err; file_t port = __file_name_lookup (file, 0, 0); diff --git a/sysdeps/mach/hurd/cthreads.c b/sysdeps/mach/hurd/cthreads.c index 5b5ed51feb..2a1a56fbda 100644 --- a/sysdeps/mach/hurd/cthreads.c +++ b/sysdeps/mach/hurd/cthreads.c @@ -19,6 +19,15 @@ #include <errno.h> #include <stdlib.h> +char __libc_lock_self0[0]; +static __thread char __libc_lock_self[0]; + +void * +__libc_get_lock_self(void) +{ + return (void*) &__libc_lock_self; +} + /* Placeholder for key creation routine from Hurd cthreads library. */ int weak_function diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index f162ff02a8..675dfcc871 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -66,25 +66,6 @@ void *_dl_random attribute_relro = NULL; struct hurd_startup_data *_dl_hurd_data; -/* This is used only within ld.so, via dl-minimal.c's __errno_location. */ -#undef errno -int errno attribute_hidden; - -/* Defining these variables here avoids the inclusion of hurdsig.c. */ -unsigned long int __hurd_sigthread_stack_base; -unsigned long int __hurd_sigthread_stack_end; -unsigned long int *__hurd_sigthread_variables; - -/* Defining these variables here avoids the inclusion of init-first.c. - We need to provide temporary storage for the per-thread variables - of the main user thread here, since it is used for storing the - `errno' variable. Note that this information is lost once we - relocate the dynamic linker. */ -static unsigned long int threadvars[_HURD_THREADVAR_MAX]; -unsigned long int __hurd_threadvar_stack_offset - = (unsigned long int) &threadvars; -unsigned long int __hurd_threadvar_stack_mask; - #define FMH defined(__i386__) #if ! FMH # define fmh() ((void)0) diff --git a/sysdeps/mach/hurd/errno-loc.c b/sysdeps/mach/hurd/errno-loc.c index 73e5e79ab9..fcca046069 100644 --- a/sysdeps/mach/hurd/errno-loc.c +++ b/sysdeps/mach/hurd/errno-loc.c @@ -1,5 +1,5 @@ /* __errno_location -- helper function for locating per-thread errno value - Copyright (C) 2002-2013 Free Software Foundation, Inc. + Copyright (C) 2013 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 @@ -16,13 +16,21 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> -#include <hurd/threadvar.h> - -int * +#ifdef IS_IN_rtld +/* + * rtld can not access TLS too early, thus rtld_errno. + * + * Instead of making __open/__close pass errno from TLS to rtld_errno, simply + * use a weak __errno_location using rtld_errno, which will be overriden by the + * libc definition. + */ +static int rtld_errno; +int * weak_function __errno_location (void) { - return (int *) __hurd_threadvar_location (_HURD_THREADVAR_ERRNO); + return &rtld_errno; } -strong_alias (__errno_location, __hurd_errno_location) -libc_hidden_def (__errno_location) +libc_hidden_weak (__errno_location) +#else +#include <../../../csu/errno-loc.c> +#endif diff --git a/sysdeps/mach/hurd/errno.c b/sysdeps/mach/hurd/errno.c deleted file mode 100644 index a29091b5e2..0000000000 --- a/sysdeps/mach/hurd/errno.c +++ /dev/null @@ -1 +0,0 @@ -/* No definition of `errno' variable on the Hurd. */ diff --git a/sysdeps/mach/hurd/fchflags.c b/sysdeps/mach/hurd/fchflags.c index 582151b885..e61c43a926 100644 --- a/sysdeps/mach/hurd/fchflags.c +++ b/sysdeps/mach/hurd/fchflags.c @@ -25,7 +25,7 @@ /* XXX should be __fchflags? */ int -fchflags (int fd, int flags) +fchflags (int fd, unsigned long int flags) { error_t err; diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c index 70180fa9c6..4622370ed9 100644 --- a/sysdeps/mach/hurd/fcntl.c +++ b/sysdeps/mach/hurd/fcntl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2013 Free Software Foundation, Inc. +/* Copyright (C) 1992-2014 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 @@ -22,6 +22,8 @@ #include <stdarg.h> #include <sys/file.h> /* XXX for LOCK_* */ +#include "flockconv.c" + /* Perform file control operations on FD. */ int __libc_fcntl (int fd, int cmd, ...) @@ -150,8 +152,8 @@ __libc_fcntl (int fd, int cmd, ...) } switch (fl->l_type) { - case F_RDLCK: cmd |= LOCK_SH; break; - case F_WRLCK: cmd |= LOCK_EX; break; + case F_RDLCK: cmd |= LOCK_SH | __LOCK_ATOMIC; break; + case F_WRLCK: cmd |= LOCK_EX | __LOCK_ATOMIC; break; case F_UNLCK: cmd |= LOCK_UN; break; default: errno = EINVAL; @@ -180,6 +182,39 @@ __libc_fcntl (int fd, int cmd, ...) return __flock (fd, cmd); } + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + { + struct flock64 *fl64 = va_arg (ap, struct flock64 *); + struct flock fl; + + if (flock64_conv (&fl, fl64)) + { + result = -1; + break; + } + + switch (cmd) + { + case F_GETLK64: + result = fcntl (fd, F_GETLK, &fl); + if (flock_conv (fl64, &fl)) + result = -1; + break; + + case F_SETLK64: + result = fcntl (fd, F_SETLK, &fl); + break; + + case F_SETLKW64: + result = fcntl (fd, F_SETLKW, &fl); + break; + } + + break; + } + case F_GETFL: /* Get per-open flags. */ if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result))) result = __hurd_dfail (fd, err); diff --git a/sysdeps/mach/hurd/flockconv.c b/sysdeps/mach/hurd/flockconv.c new file mode 100644 index 0000000000..4438784740 --- /dev/null +++ b/sysdeps/mach/hurd/flockconv.c @@ -0,0 +1,69 @@ +/* Convert between `struct flock' format, and `struct flock64' format. + Copyright (C) 2014 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, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <fcntl.h> + +static inline int +flock64_conv (struct flock *buf, const struct flock64 *buf64) +{ + if (sizeof *buf == sizeof *buf64 + && sizeof buf->l_start == sizeof buf64->l_start + && sizeof buf->l_len == sizeof buf64->l_len) + { + *buf = *(struct flock *) buf64; + return 0; + } + + buf->l_type = buf64->l_type; + buf->l_whence = buf64->l_whence; + buf->l_start = buf64->l_start; + buf->l_len = buf64->l_len; + buf->l_pid = buf64->l_pid; + + if ((sizeof buf->l_start != sizeof buf64->l_start + && buf->l_start != buf64->l_start) + || (sizeof buf->l_len != sizeof buf64->l_len + && buf->l_len != buf64->l_len)) + { + __set_errno (EOVERFLOW); + return -1; + } + + return 0; +} + +static inline int +flock_conv (struct flock64 *buf64, const struct flock *buf) +{ + if (sizeof *buf == sizeof *buf64 + && sizeof buf->l_start == sizeof buf64->l_start + && sizeof buf->l_len == sizeof buf64->l_len) + { + *buf64 = *(struct flock64 *) buf; + return 0; + } + + buf64->l_type = buf->l_type; + buf64->l_whence = buf->l_whence; + buf64->l_start = buf->l_start; + buf64->l_len = buf->l_len; + buf64->l_pid = buf->l_pid; + + return 0; +} diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c index f5d8063f1f..dd87d95b79 100644 --- a/sysdeps/mach/hurd/fork.c +++ b/sysdeps/mach/hurd/fork.c @@ -19,6 +19,7 @@ #include <unistd.h> #include <hurd.h> #include <hurd/signal.h> +#include <hurd/threadvar.h> #include <setjmp.h> #include <thread_state.h> #include <sysdep.h> /* For stack growth direction. */ @@ -129,9 +130,13 @@ __fork (void) ports_locked = 1; + /* Keep our SS locked while stopping other threads, so they don't get a + chance to have it locked in the copied space. */ + __spin_lock (&ss->lock); /* Stop all other threads while copying the address space, so nothing changes. */ err = __proc_dostop (_hurd_ports[INIT_PORT_PROC].port, ss->thread); + __spin_unlock (&ss->lock); if (!err) { stopped = 1; @@ -505,19 +510,17 @@ __fork (void) (natural_t *) &state, &statecount)) LOSE; #if STACK_GROWTH_UP -#define THREADVAR_SPACE (__hurd_threadvar_max \ - * sizeof *__hurd_sightread_variables) if (__hurd_sigthread_stack_base == 0) { state.SP &= __hurd_threadvar_stack_mask; - state.SP += __hurd_threadvar_stack_offset + THREADVAR_SPACE; + state.SP += __hurd_threadvar_stack_offset; } else state.SP = __hurd_sigthread_stack_base; #else if (__hurd_sigthread_stack_end == 0) { - /* The signal thread has a normal stack assigned by cthreads. + /* The signal thread has a stack assigned by cthreads. The threadvar_stack variables conveniently tell us how to get to the highest address in the stack, just below the per-thread variables. */ diff --git a/sysdeps/mach/hurd/futimens.c b/sysdeps/mach/hurd/futimens.c new file mode 100644 index 0000000000..218779d4c3 --- /dev/null +++ b/sysdeps/mach/hurd/futimens.c @@ -0,0 +1,50 @@ +/* futimes -- change access and modification times of open file. Hurd version. + Copyright (C) 2002-2014 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, see + <http://www.gnu.org/licenses/>. */ + +#include <sys/time.h> +#include <errno.h> +#include <stddef.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Change the access time of FD to TSP[0] and + the modification time of FD to TSP[1]. */ +int +__futimens (int fd, const struct timespec tsp[2]) +{ + time_value_t atime, mtime; + error_t err; + + if (tsp == NULL) + { + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + atime.microseconds = mtime.microseconds = -1; + } + else + { + atime.seconds = tsp[0].tv_sec; + atime.microseconds = tsp[0].tv_nsec / 1000; + mtime.seconds = tsp[1].tv_sec; + mtime.microseconds = tsp[1].tv_nsec / 1000; + } + + err = HURD_DPORT_USE (fd, __file_utimes (port, atime, mtime)); + return err ? __hurd_dfail (fd, err) : 0; +} +weak_alias (__futimens, futimens) diff --git a/sysdeps/mach/hurd/gai_misc.h b/sysdeps/mach/hurd/gai_misc.h new file mode 100644 index 0000000000..ee8117fa96 --- /dev/null +++ b/sysdeps/mach/hurd/gai_misc.h @@ -0,0 +1,44 @@ +#include <signal.h> +#include <pthread.h> + +#define gai_start_notify_thread __gai_start_notify_thread +#define gai_create_helper_thread __gai_create_helper_thread + +extern inline void +__gai_start_notify_thread (void) +{ + sigset_t ss; + sigemptyset (&ss); + sigprocmask(SIG_SETMASK, &ss, NULL); +} + +extern inline int +__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), + void *arg) +{ + pthread_attr_t attr; + + /* Make sure the thread is created detached. */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + /* The helper thread needs only very little resources. */ + (void) pthread_attr_setstacksize (&attr, 0x10000); + + /* Block all signals in the helper thread. To do this thoroughly we + temporarily have to block all signals here. */ + sigset_t ss; + sigset_t oss; + sigfillset (&ss); + sigprocmask(SIG_SETMASK, &ss, &oss); + + int ret = pthread_create (threadp, &attr, tf, arg); + + /* Restore the signal mask. */ + sigprocmask(SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + return ret; +} + +#include_next <gai_misc.h> diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c index d981839b44..14d0bf844c 100644 --- a/sysdeps/mach/hurd/i386/init-first.c +++ b/sysdeps/mach/hurd/i386/init-first.c @@ -152,15 +152,6 @@ init (int *data) char **argv = (void *) (data + 1); char **envp = &argv[argc + 1]; struct hurd_startup_data *d; - unsigned long int threadvars[_HURD_THREADVAR_MAX]; - - /* Provide temporary storage for thread-specific variables on the - startup stack so the cthreads initialization code can use them - for malloc et al, or so we can use malloc below for the real - threadvars array. */ - memset (threadvars, 0, sizeof threadvars); - threadvars[_HURD_THREADVAR_LOCALE] = (unsigned long int) &_nl_global_locale; - __hurd_threadvar_stack_offset = (unsigned long int) threadvars; /* Since the cthreads initialization code uses malloc, and the malloc initialization code needs to get at the environment, make @@ -206,13 +197,6 @@ init (int *data) __pthread_initialize_minimal(); #endif - /* The user might have defined a value for this, to get more variables. - Otherwise it will be zero on startup. We must make sure it is set - properly before before cthreads initialization, so cthreads can know - how much space to leave for thread variables. */ - if (__hurd_threadvar_max < _HURD_THREADVAR_MAX) - __hurd_threadvar_max = _HURD_THREADVAR_MAX; - /* After possibly switching stacks, call `init1' (above) with the user code as the return address, and the argument data immediately above @@ -228,11 +212,6 @@ init (int *data) __libc_stack_end = newsp; - /* Copy per-thread variables from that temporary - area onto the new cthread stack. */ - memcpy (__hurd_threadvar_location_from_sp (0, newsp), - threadvars, sizeof threadvars); - /* Copy the argdata from the old stack to the new one. */ newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data, (char *) d - (char *) data); @@ -273,25 +252,11 @@ init (int *data) } else { - /* We are not using cthreads, so we will have just a single allocated - area for the per-thread variables of the main user thread. */ - unsigned long int *array; unsigned int i; int usercode; void call_init1 (void); - array = malloc (__hurd_threadvar_max * sizeof (unsigned long int)); - if (array == NULL) - __libc_fatal ("Can't allocate single-threaded thread variables."); - - /* Copy per-thread variables from the temporary array into the - newly malloc'd space. */ - memcpy (array, threadvars, sizeof threadvars); - __hurd_threadvar_stack_offset = (unsigned long int) array; - for (i = _HURD_THREADVAR_MAX; i < __hurd_threadvar_max; ++i) - array[i] = 0; - /* The argument data is just above the stack frame we will unwind by returning. Mutate our own return address to run the code below. */ /* The following expression would typically be written as diff --git a/sysdeps/mach/hurd/i386/makecontext-helper.c b/sysdeps/mach/hurd/i386/makecontext-helper.c index 6db3b7e018..e604488264 100644 --- a/sysdeps/mach/hurd/i386/makecontext-helper.c +++ b/sysdeps/mach/hurd/i386/makecontext-helper.c @@ -22,6 +22,7 @@ #include <string.h> #include <ucontext.h> +#if 0 void __makecontext_helper (ucontext_t *ucp) @@ -67,3 +68,4 @@ __makecontext_helper (ucontext_t *ucp) ucp->uc_stack.ss_size -= t_size; } } +#endif diff --git a/sysdeps/mach/hurd/i386/makecontext.S b/sysdeps/mach/hurd/i386/makecontext.S index 7f3f6b0b90..b81403b04f 100644 --- a/sysdeps/mach/hurd/i386/makecontext.S +++ b/sysdeps/mach/hurd/i386/makecontext.S @@ -27,7 +27,7 @@ ENTRY(__makecontext) subl $4, %esp cfi_adjust_cfa_offset (4) movl %eax, (%esp) - call HIDDEN_JUMPTARGET (__makecontext_helper) + /* call HIDDEN_JUMPTARGET (__makecontext_helper) */ addl $4, %esp cfi_adjust_cfa_offset (-4) diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c index 01546587e5..f3015280c8 100644 --- a/sysdeps/mach/hurd/i386/sigreturn.c +++ b/sysdeps/mach/hurd/i386/sigreturn.c @@ -68,7 +68,7 @@ __sigreturn (struct sigcontext *scp) if (scp->sc_onstack) { - ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */ + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX cannot unlock until off sigstack */ abort (); } @@ -77,8 +77,7 @@ __sigreturn (struct sigcontext *scp) /* Destroy the MiG reply port used by the signal handler, and restore the reply port in use by the thread when interrupted. */ - reply_port = - (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); + reply_port = &__hurd_local_reply_port; if (*reply_port) { mach_port_t port = *reply_port; diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h index 25623e910c..d6a387d3c0 100644 --- a/sysdeps/mach/hurd/i386/tls.h +++ b/sysdeps/mach/hurd/i386/tls.h @@ -53,11 +53,24 @@ | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ } +# define HURD_DESC_TLS(desc) \ + ({ \ + (tcbhead_t *) ( (desc->low_word >> 16) \ + | ((desc->high_word & 0xff) << 16) \ + | (desc->high_word & 0xff000000) \ + );}) + +#define __LIBC_NO_TLS() \ + ({ unsigned short ds, gs; \ + asm ("movw %%ds,%w0; movw %%gs,%w1" : "=q" (ds), "=q" (gs)); \ + ds == gs; }) static inline const char * __attribute__ ((unused)) _hurd_tls_init (tcbhead_t *tcb, int secondcall) { HURD_TLS_DESC_DECL (desc, tcb); + thread_t self = __mach_thread_self (); + const char *msg = NULL; if (!secondcall) { @@ -65,25 +78,26 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall) from the TLS point of view. */ tcb->tcb = tcb; - /* Cache our thread port. */ - tcb->self = __mach_thread_self (); - /* Get the first available selector. */ int sel = -1; - kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc); + kern_return_t err = __i386_set_gdt (self, &sel, desc); if (err == MIG_BAD_ID) { /* Old kernel, use a per-thread LDT. */ sel = 0x27; - err = __i386_set_ldt (tcb->self, sel, &desc, 1); + err = __i386_set_ldt (self, sel, &desc, 1); assert_perror (err); if (err) - return "i386_set_ldt failed"; + { + msg = "i386_set_ldt failed"; + goto out; + } } else if (err) { assert_perror (err); /* Separate from above with different line #. */ - return "i386_set_gdt failed"; + msg = "i386_set_gdt failed"; + goto out; } /* Now install the new selector. */ @@ -96,21 +110,29 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall) asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0)); if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ { - kern_return_t err = __i386_set_ldt (tcb->self, sel, &desc, 1); + kern_return_t err = __i386_set_ldt (self, sel, &desc, 1); assert_perror (err); if (err) - return "i386_set_ldt failed"; + { + msg = "i386_set_ldt failed"; + goto out; + } } else { - kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc); + kern_return_t err = __i386_set_gdt (self, &sel, desc); assert_perror (err); if (err) - return "i386_set_gdt failed"; + { + msg = "i386_set_gdt failed"; + goto out; + } } } - return 0; +out: + __mach_port_deallocate (__mach_task_self (), self); + return msg; } /* Code to initially initialize the thread pointer. This might need @@ -126,6 +148,20 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall) : "i" (offsetof (tcbhead_t, tcb))); \ __tcb;}) +/* Return the TCB address of a thread given its state. */ +# define THREAD_TCB(thread, thread_state) \ + ({ int __sel = (thread_state)->basic.gs; \ + struct descriptor __desc, *___desc = &__desc; \ + unsigned int __count = 1; \ + kern_return_t __err; \ + if (__builtin_expect (__sel, 0x48) & 4) /* LDT selector */ \ + __err = __i386_get_ldt ((thread), __sel, 1, &___desc, &__count); \ + else \ + __err = __i386_get_gdt ((thread), __sel, &__desc); \ + assert_perror (__err); \ + assert (__count == 1); \ + HURD_DESC_TLS(___desc);}) + /* Install new dtv for current thread. */ # define INSTALL_NEW_DTV(dtvp) \ ({ asm volatile ("movl %0,%%gs:%P1" \ @@ -151,7 +187,7 @@ _hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state) struct descriptor desc, *_desc = &desc; kern_return_t err; - unsigned int count; + unsigned int count = 1; if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ err = __i386_get_ldt (orig, sel, 1, &_desc, &count); diff --git a/sysdeps/mach/hurd/jmp-unwind.c b/sysdeps/mach/hurd/jmp-unwind.c index bdc24b9a69..0422d9eb19 100644 --- a/sysdeps/mach/hurd/jmp-unwind.c +++ b/sysdeps/mach/hurd/jmp-unwind.c @@ -49,9 +49,8 @@ _longjmp_unwind (jmp_buf env, int val) /* All access to SS->active_resources must take place inside a critical section where signal handlers cannot run. */ - __spin_lock (&ss->lock); - assert (! __spin_lock_locked (&ss->critical_section_lock)); __spin_lock (&ss->critical_section_lock); + __spin_lock (&ss->lock); /* Remove local signal preemptors being unwound past. */ while (ss->preemptors && diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c index f0b5172e6f..1b3ff87319 100644 --- a/sysdeps/mach/hurd/mig-reply.c +++ b/sysdeps/mach/hurd/mig-reply.c @@ -18,26 +18,20 @@ #include <mach.h> #include <hurd/threadvar.h> -#define GETPORT \ - mach_port_t *portloc = \ - (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY) -#define reply_port (*(use_threadvar ? portloc : &global_reply_port)) - -static int use_threadvar; -static mach_port_t global_reply_port; - /* These functions are called by MiG-generated code. */ +mach_port_t __hurd_reply_port0; + /* Called by MiG to get a reply port. */ mach_port_t __mig_get_reply_port (void) { - GETPORT; - - if (reply_port == MACH_PORT_NULL) - reply_port = __mach_reply_port (); + if (__hurd_local_reply_port == MACH_PORT_NULL || + (&__hurd_local_reply_port != &__hurd_reply_port0 + && __hurd_local_reply_port == __hurd_reply_port0)) + __hurd_local_reply_port = __mach_reply_port (); - return reply_port; + return __hurd_local_reply_port; } weak_alias (__mig_get_reply_port, mig_get_reply_port) @@ -45,12 +39,8 @@ weak_alias (__mig_get_reply_port, mig_get_reply_port) void __mig_dealloc_reply_port (mach_port_t arg) { - mach_port_t port; - - GETPORT; - - port = reply_port; - reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */ + mach_port_t port = __hurd_local_reply_port; + __hurd_local_reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */ if (MACH_PORT_VALID (port)) __mach_port_mod_refs (__mach_task_self (), port, @@ -73,15 +63,6 @@ weak_alias (__mig_put_reply_port, mig_put_reply_port) void __mig_init (void *stack) { - use_threadvar = stack != 0; - - if (use_threadvar) - { - /* Recycle the reply port used before multithreading was enabled. */ - mach_port_t *portloc = (mach_port_t *) - __hurd_threadvar_location_from_sp (_HURD_THREADVAR_MIG_REPLY, stack); - *portloc = global_reply_port; - global_reply_port = MACH_PORT_NULL; - } + /* Do nothing. */ } weak_alias (__mig_init, mig_init) diff --git a/sysdeps/mach/hurd/mmap.c b/sysdeps/mach/hurd/mmap.c index 6ee314603b..b9478158a9 100644 --- a/sysdeps/mach/hurd/mmap.c +++ b/sysdeps/mach/hurd/mmap.c @@ -97,6 +97,14 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset) } switch (prot & (PROT_READ|PROT_WRITE)) { + /* Although it apparently doesn't make sense to map a file with + protection set to PROT_NONE, it is actually sometimes done. + In particular, that's how localedef reserves some space for + the locale archive file, the rationale being that some + implementations take into account whether the mapping is + anonymous or not when selecting addresses. */ + case PROT_NONE: + case PROT_READ: memobj = robj; if (wobj != MACH_PORT_NULL) @@ -126,8 +134,6 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset) return (__ptr_t) (long int) __hurd_fail (EACCES); } break; - default: /* impossible */ - return 0; } break; /* XXX handle MAP_NOEXTEND */ diff --git a/sysdeps/mach/hurd/profil.c b/sysdeps/mach/hurd/profil.c index 328bb29df2..417691ee03 100644 --- a/sysdeps/mach/hurd/profil.c +++ b/sysdeps/mach/hurd/profil.c @@ -139,7 +139,7 @@ __profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale) weak_alias (__profil, profil) /* Fetch PC samples. This function must be very careful not to depend - on Hurd threadvar variables. We arrange that by using a special + on Hurd TLS variables. We arrange that by using a special stub arranged for at the end of this file. */ static void fetch_samples (void) @@ -175,7 +175,7 @@ fetch_samples (void) } -/* This function must be very careful not to depend on Hurd threadvar +/* This function must be very careful not to depend on Hurd TLS variables. We arrange that by using special stubs arranged for at the end of this file. */ static void @@ -267,7 +267,7 @@ text_set_element (_hurd_fork_child_hook, fork_profil_child); are fatal in profile_waiter anyhow. */ #define __mig_put_reply_port(foo) -/* Use our static variable instead of the usual threadvar mechanism for +/* Use our static variable instead of the usual TLS mechanism for this. */ #define __mig_get_reply_port() profil_reply_port diff --git a/sysdeps/mach/hurd/reboot.c b/sysdeps/mach/hurd/reboot.c index 60d96eaad2..51c3d737ac 100644 --- a/sysdeps/mach/hurd/reboot.c +++ b/sysdeps/mach/hurd/reboot.c @@ -18,6 +18,7 @@ #include <errno.h> #include <unistd.h> #include <hurd.h> +#include <hurd/paths.h> #include <hurd/startup.h> #include <sys/reboot.h> @@ -33,8 +34,8 @@ reboot (int howto) if (err) return __hurd_fail (EPERM); - err = __USEPORT (PROC, __proc_getmsgport (port, 1, &init)); - if (!err) + init = __file_name_lookup (_SERVERS_STARTUP, 0, 0); + if (init != MACH_PORT_NULL) { err = __startup_reboot (init, hostpriv, howto); __mach_port_deallocate (__mach_task_self (), init); diff --git a/sysdeps/mach/hurd/sendmsg.c b/sysdeps/mach/hurd/sendmsg.c index e68e5c10bf..82d5d68dc3 100644 --- a/sysdeps/mach/hurd/sendmsg.c +++ b/sysdeps/mach/hurd/sendmsg.c @@ -138,6 +138,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags) nports++; /* We pass the flags in the control data. */ fds[i] = descriptor->flags; + err; })); if (err) diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c index 5ee63e15cd..4e7b8f577a 100644 --- a/sysdeps/mach/hurd/spawni.c +++ b/sysdeps/mach/hurd/spawni.c @@ -235,7 +235,6 @@ __spawni (pid_t *pid, const char *file, ss = _hurd_self_sigstate (); - assert (! __spin_lock_locked (&ss->critical_section_lock)); __spin_lock (&ss->critical_section_lock); _hurd_sigstate_lock (ss); diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h index ca4398fcf6..852c0179f7 100644 --- a/sysdeps/mach/hurd/tls.h +++ b/sysdeps/mach/hurd/tls.h @@ -47,6 +47,10 @@ typedef struct void *tcb; /* Points to this structure. */ dtv_t *dtv; /* Vector of pointers to TLS data. */ thread_t self; /* This thread's control port. */ + + /* Keep this field last */ + mach_port_t reply_port; /* This thread's reply port. */ + struct hurd_sigstate *_hurd_sigstate; } tcbhead_t; diff --git a/sysdeps/pthread/aio_misc.c b/sysdeps/pthread/aio_misc.c index 79153c8b78..615a11f17d 100644 --- a/sysdeps/pthread/aio_misc.c +++ b/sysdeps/pthread/aio_misc.c @@ -311,7 +311,10 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) if (operation == LIO_SYNC || operation == LIO_DSYNC) aiocbp->aiocb.aio_reqprio = 0; else if (aiocbp->aiocb.aio_reqprio < 0 - || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX) +#ifdef AIO_PRIO_DELTA_MAX + || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX +#endif + ) { /* Invalid priority value. */ __set_errno (EINVAL); |