From d969d27b78665c062578a2e38c3df7a0d545a6df Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 23 Sep 2013 18:15:08 +0200 Subject: Make errno use TLS instead of threadvar --- hurd/Versions | 3 --- 1 file changed, 3 deletions(-) (limited to 'hurd') diff --git a/hurd/Versions b/hurd/Versions index 83c8ab1826..2264faf25e 100644 --- a/hurd/Versions +++ b/hurd/Versions @@ -36,9 +36,6 @@ libc { __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; -- cgit v1.2.3 From f1cc02b3342389c782cadfc94a047ba6200b0eb8 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 14 Oct 2013 03:38:29 +0200 Subject: Replace mig_reply_port threadvar with a TLS variable --- hurd/hurd/threadvar.h | 3 +++ hurd/hurdsig.c | 15 +++++++++------ hurd/sigunwind.c | 3 +-- sysdeps/mach/hurd/i386/sigreturn.c | 3 +-- sysdeps/mach/hurd/mig-reply.c | 39 ++++++++++---------------------------- sysdeps/mach/hurd/tls.h | 1 + 6 files changed, 25 insertions(+), 39 deletions(-) (limited to 'hurd') diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h index 786db14a01..5dba21cef1 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -20,6 +20,7 @@ #define _HURD_THREADVAR_H #include +#include /* The per-thread variables are found by ANDing this mask with the value of the stack pointer and then adding this offset. @@ -112,5 +113,7 @@ __hurd_threadvar_location (enum __hurd_threadvar_index __index) __thread_stack_pointer ()); } +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/hurdsig.c b/hurd/hurdsig.c index 46f24d5e81..e38a4b2577 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -234,11 +234,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. */ @@ -323,7 +323,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); @@ -835,7 +836,8 @@ _hurd_internal_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 @@ -901,7 +903,8 @@ _hurd_internal_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) { diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c index de966aa09b..40af749479 100644 --- a/hurd/sigunwind.c +++ b/hurd/sigunwind.c @@ -38,8 +38,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/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c index 92727b5424..1953096e5b 100644 --- a/sysdeps/mach/hurd/i386/sigreturn.c +++ b/sysdeps/mach/hurd/i386/sigreturn.c @@ -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/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 #include -#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/tls.h b/sysdeps/mach/hurd/tls.h index 230f90705f..a5f65ffccb 100644 --- a/sysdeps/mach/hurd/tls.h +++ b/sysdeps/mach/hurd/tls.h @@ -47,6 +47,7 @@ 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. */ + mach_port_t reply_port; /* This thread's reply port. */ } tcbhead_t; -- cgit v1.2.3 From 1b8fb80cd64c4250c7ba7d50941699c96e2c8741 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 20 Oct 2013 17:57:20 +0200 Subject: Use a macro instead of an inline for __libc_no_tls --- hurd/hurd/threadvar.h | 2 +- sysdeps/mach/hurd/bits/libc-lock.h | 2 +- sysdeps/mach/hurd/i386/tls.h | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'hurd') diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h index 5dba21cef1..d5dd1419a6 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -114,6 +114,6 @@ __hurd_threadvar_location (enum __hurd_threadvar_index __index) } extern mach_port_t __hurd_reply_port0; -#define __hurd_local_reply_port (*(__libc_no_tls() ? &__hurd_reply_port0 : &THREAD_SELF->reply_port)) +#define __hurd_local_reply_port (*(__LIBC_NO_TLS() ? &__hurd_reply_port0 : &THREAD_SELF->reply_port)) #endif /* hurd/threadvar.h */ diff --git a/sysdeps/mach/hurd/bits/libc-lock.h b/sysdeps/mach/hurd/bits/libc-lock.h index c451a3e0e0..9c25b4c090 100644 --- a/sysdeps/mach/hurd/bits/libc-lock.h +++ b/sysdeps/mach/hurd/bits/libc-lock.h @@ -36,7 +36,7 @@ typedef __libc_lock_recursive_t __rtld_lock_recursive_t; extern char __libc_lock_self0[0]; extern __thread char __libc_lock_self[0]; -#define __libc_lock_owner_self() (__libc_no_tls() ? &__libc_lock_self0 : (void*) &__libc_lock_self) +#define __libc_lock_owner_self() (__LIBC_NO_TLS() ? &__libc_lock_self0 : (void*) &__libc_lock_self) #else typedef struct __libc_lock_opaque__ __libc_lock_t; diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h index 11cd04e15e..7159484cb6 100644 --- a/sysdeps/mach/hurd/i386/tls.h +++ b/sysdeps/mach/hurd/i386/tls.h @@ -60,12 +60,10 @@ | (desc->high_word & 0xff000000) \ );}) -static inline int __libc_no_tls(void) -{ - unsigned short ds, gs; - asm ("movw %%ds,%w0; movw %%gs,%w1" : "=q" (ds), "=q" (gs)); - return ds == gs; -} +#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) -- cgit v1.2.3 From c85d2864b23774e723c8e4610ac0cd737dfa40a4 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 20 Oct 2013 18:13:31 +0200 Subject: Convert sigstate to TLS --- hurd/hurd/signal.h | 23 ++++++++++++++--------- hurd/hurdsig.c | 3 +++ sysdeps/mach/hurd/Versions | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'hurd') diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index d4079efe00..1efa4a29be 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -129,14 +129,13 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void) #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline #endif +extern __thread struct hurd_sigstate *_hurd_sigstate; _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { - struct hurd_sigstate **location = - (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); - if (*location == NULL) - *location = _hurd_thread_sigstate (__mach_thread_self ()); - return *location; + if (_hurd_sigstate == NULL) + _hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + return _hurd_sigstate; } /* Thread listening on our message port; also called the "signal thread". */ @@ -167,16 +166,22 @@ extern int _hurd_core_limit; _HURD_SIGNAL_H_EXTERN_INLINE void * _hurd_critical_section_lock (void) { - struct hurd_sigstate **location = - (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); - struct hurd_sigstate *ss = *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 + + ss = _hurd_sigstate; if (ss == NULL) { /* 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 way; this locks the sigstate lock. */ - ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); + ss = _hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); __spin_unlock (&ss->lock); } diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index e38a4b2577..ee4227a294 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -50,6 +50,9 @@ unsigned long int __hurd_sigthread_stack_base; unsigned long int __hurd_sigthread_stack_end; unsigned long int *__hurd_sigthread_variables; +/* Per-thread signal state. */ +__thread struct hurd_sigstate *_hurd_sigstate; + /* Linked-list of per-thread signal state. */ struct hurd_sigstate *_hurd_sigstates; diff --git a/sysdeps/mach/hurd/Versions b/sysdeps/mach/hurd/Versions index c9cdddcb3e..1f04244aea 100644 --- a/sysdeps/mach/hurd/Versions +++ b/sysdeps/mach/hurd/Versions @@ -7,6 +7,7 @@ libc { # Functions shared with the dynamic linker __libc_read; __libc_write; __libc_lseek64; __libc_lock_self0; __libc_lock_self; + _hurd_sigstate; _dl_init_first; } @@ -35,5 +36,6 @@ ld { # functions that must be shared with libc __libc_read; __libc_write; __libc_lseek64; __libc_lock_self0; __libc_lock_self; + _hurd_sigstate; } } -- cgit v1.2.3 From d75af560cf903e0daeb0e92b1f3d516b1d8254df Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 24 Oct 2013 23:56:07 +0200 Subject: Do not expose libc internals about ports and signals outside libc --- hurd/hurd/fd.h | 2 +- hurd/hurd/port.h | 12 ++++++------ hurd/hurd/signal.h | 6 +++--- hurd/hurd/threadvar.h | 4 ++-- hurd/hurd/userlink.h | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'hurd') diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h index 5776e21e8b..cd8edccdc2 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 _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..ce55154364 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 _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 _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 _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 _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 _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 _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 8e2410029c..ae581f68b2 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -129,7 +129,7 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void) #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline #endif -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { @@ -168,7 +168,7 @@ extern int _hurd_core_limit; void *_hurd_critical_section_lock (void); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC _HURD_SIGNAL_H_EXTERN_INLINE void * _hurd_critical_section_lock (void) { @@ -198,7 +198,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 _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..e8013ce03f 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -82,7 +82,7 @@ enum __hurd_threadvar_index extern unsigned long int *__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, void *__sp); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC _HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * __hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, void *__sp) @@ -108,7 +108,7 @@ __hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW the same stack frame by different threads. */ __attribute__ ((__const__)); -#ifdef __USE_EXTERN_INLINES +#if defined __USE_EXTERN_INLINES && defined _LIBC _HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * __hurd_threadvar_location (enum __hurd_threadvar_index __index) { diff --git a/hurd/hurd/userlink.h b/hurd/hurd/userlink.h index c6286f30c5..4962f0cb65 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 _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 _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 _HURD_USERLINK_H_EXTERN_INLINE int _hurd_userlink_clear (struct hurd_userlink **chainp) { -- cgit v1.2.3 From b3320e243e29a0451fb5aa6d39c6bfe2200504dc Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 25 Oct 2013 00:37:58 +0200 Subject: Drop threadvars entirely --- hurd/Versions | 4 +- hurd/hurd/signal.h | 1 - hurd/hurd/threadvar.h | 78 ++--------------------------- hurd/hurdsig.c | 32 ++++++++---- hurd/hurdstartup.c | 1 - hurd/sigunwind.c | 1 + sysdeps/mach/hurd/Versions | 2 - sysdeps/mach/hurd/dl-sysdep.c | 15 ------ sysdeps/mach/hurd/fork.c | 7 ++- sysdeps/mach/hurd/i386/init-first.c | 34 ------------- sysdeps/mach/hurd/i386/makecontext-helper.c | 2 + sysdeps/mach/hurd/i386/makecontext.S | 2 +- sysdeps/mach/hurd/profil.c | 6 +-- 13 files changed, 37 insertions(+), 148 deletions(-) (limited to 'hurd') diff --git a/hurd/Versions b/hurd/Versions index 2264faf25e..738281da15 100644 --- a/hurd/Versions +++ b/hurd/Versions @@ -25,14 +25,13 @@ 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; @@ -158,6 +157,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/signal.h b/hurd/hurd/signal.h index e9e0e0da1a..e633debe7c 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -40,7 +40,6 @@ #include /* For `struct mutex'. */ #include /* For `jmp_buf'. */ #include -#include /* We cache sigstate in a threadvar. */ struct hurd_signal_preemptor; /* */ diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h index 6dad87ab00..888d5354e9 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -31,93 +31,23 @@ __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); - -#if defined __USE_EXTERN_INLINES && defined _LIBC -_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 /* 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__)); - -#if defined __USE_EXTERN_INLINES && defined _LIBC -_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)) diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index ee4227a294..1d87e2e973 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -20,6 +20,7 @@ #include #include /* For `struct mutex'. */ +#include #include #include @@ -48,7 +49,6 @@ thread_t _hurd_sigthread; /* 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; /* Per-thread signal state. */ __thread struct hurd_sigstate *_hurd_sigstate; @@ -1261,7 +1261,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); @@ -1276,12 +1280,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. */ @@ -1292,6 +1290,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 @@ -1301,9 +1300,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 #include #include -#include #include #include #include diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c index 40af749479..a1819a2b36 100644 --- a/hurd/sigunwind.c +++ b/hurd/sigunwind.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/sysdeps/mach/hurd/Versions b/sysdeps/mach/hurd/Versions index 1f04244aea..9ecdbaf90e 100644 --- a/sysdeps/mach/hurd/Versions +++ b/sysdeps/mach/hurd/Versions @@ -16,8 +16,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 diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index b5e7636e76..cea4a95991 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -64,21 +64,6 @@ hp_timing_t _dl_cpuclock_offset; struct hurd_startup_data *_dl_hurd_data; -/* 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/fork.c b/sysdeps/mach/hurd/fork.c index c3f88a90d8..6e7fe5f1ee 100644 --- a/sysdeps/mach/hurd/fork.c +++ b/sysdeps/mach/hurd/fork.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include /* For stack growth direction. */ @@ -497,19 +498,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/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c index 6cfbf48105..e9d1f04dfe 100644 --- a/sysdeps/mach/hurd/i386/init-first.c +++ b/sysdeps/mach/hurd/i386/init-first.c @@ -155,14 +155,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); - __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 @@ -208,13 +200,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 @@ -230,11 +215,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); @@ -275,25 +255,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 #include +#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/profil.c b/sysdeps/mach/hurd/profil.c index e4be9483c4..7cae6ac7f6 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 -- cgit v1.2.3 From e88815ece5d165e095966fa9b7ae50933b19a051 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Sat, 21 Dec 2013 21:55:28 +0100 Subject: Hurd: fix sigstate locking It looks like _hurd_thread_sigstate used to return with the sigstate lock held long ago, but since that's no longer the case, don't unlock something that isn't locked. Note that it's unlikely this change fixes anything in practice since its current implementation (on i386) makes this call a nop. * hurd/hurd/signal.h (_hurd_critical_section_lock): Don't unlock sigstate. --- .topdeps | 2 +- .topmsg | 22 +++++++++------------- hurd/hurd/signal.h | 3 +-- 3 files changed, 11 insertions(+), 16 deletions(-) (limited to 'hurd') diff --git a/.topdeps b/.topdeps index e7a14c6ca9..180b47c18b 100644 --- a/.topdeps +++ b/.topdeps @@ -1 +1 @@ -0323d08657f111267efa47bd448fbf6cd76befe8 +baseline diff --git a/.topmsg b/.topmsg index dd6634c886..976127d754 100644 --- a/.topmsg +++ b/.topmsg @@ -1,16 +1,12 @@ -Subject: Baseline for our topic branches. +From: Richard Braun +Subject: [PATCH] Hurd: fix sigstate locking ---- +It looks like _hurd_thread_sigstate used to return with the sigstate +lock held long ago, but since that's no longer the case, don't unlock +something that isn't locked. -This need not strictly be a TopGit branch, but it is for easy synchronization -between different machines. +Note that it's unlikely this change fixes anything in practice since +its current implementation (on i386) makes this call a nop. -As the baseline is merged into the topic branches, it is forward-only. - -To advance it: - - $ echo [SHA1] > .topdeps - $ git commit -m Advance. -- .topdeps - $ tg update - ---- +* hurd/hurd/signal.h (_hurd_critical_section_lock): Don't unlock +sigstate. diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index d4079efe00..13c5f0e03b 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -175,9 +175,8 @@ _hurd_critical_section_lock (void) /* 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 - way; this locks the sigstate lock. */ + way. */ ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); - __spin_unlock (&ss->lock); } if (! __spin_try_lock (&ss->critical_section_lock)) -- cgit v1.2.3 From 512a1659ed7c20fa94e32ceb9b3bdf715b1253e9 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Mon, 23 Dec 2013 11:57:58 +0100 Subject: Hurd: make sigstates hold a reference on thread ports This change is required in order to correctly release per-thread resources. Directly reusing the threading library reference isn't possible since the sigstate is also used early in the main thread, before threading is initialized. * hurd/hurd/signal.h (_hurd_self_sigstate): Drop thread reference after calling _hurd_thread_sigstate. (_hurd_critical_section_lock): Likewise. * hurd/hurdsig.c (_hurd_thread_sigstate): Add a reference on the thread. (_hurd_sigstate_delete): Drop thread reference. --- .topdeps | 2 +- .topmsg | 83 +++++++++--------------------------------------------- hurd/hurd/signal.h | 17 +++++++++-- hurd/hurdsig.c | 17 +++++++++-- 4 files changed, 42 insertions(+), 77 deletions(-) (limited to 'hurd') diff --git a/.topdeps b/.topdeps index 54fb4356a1..e83f8a04b8 100644 --- a/.topdeps +++ b/.topdeps @@ -1 +1 @@ -t/hurdsig-fixes +t/hurdsig-global-dispositions diff --git a/.topmsg b/.topmsg index 3353306c4d..4036303c98 100644 --- a/.topmsg +++ b/.topmsg @@ -1,70 +1,13 @@ -Subject: [PATCH] Global signal dispositions. - -Although they should not change the -default behaviors of signals for cthread programs, these patches add -new functions which can be used by libpthread to enable -POSIX-conforming behavior of signals on a per-thread basis. - -YYYY-MM-DD Jeremie Koenig - - e407ae3 Hurd signals: implement global signal dispositions - 38eb4b3 Hurd signals: provide a sigstate destructor - 344dfd6 Hurd signals: fix sigwait() for global signals - fb055f2 Hurd signals: fix global untraced signals. - -YYYY-MM-DD Thomas Schwinge - - * sysdeps/mach/hurd/fork.c (__fork): In the child, reinitialize - the global sigstate's lock. - -This is work in progress. - -This cures an issue that would very rarely cause a deadlock in the child -in fork, tries to unlock ss' critical section lock at the end of fork. -This will typically (always?) be observed in /bin/sh, which is not -surprising as that is the foremost caller of fork. - -To reproduce an intermediate state, add an endless loop if -_hurd_global_sigstate is locked after __proc_dostop (cast through -volatile); that is, while still being in the fork's parent process. - -When that triggers (use the libtool testsuite), the signal thread has -already locked ss (which is _hurd_global_sigstate), and is stuck at -hurdsig.c:685 in post_signal, trying to lock _hurd_siglock (which the -main thread already has locked and keeps locked until after -__task_create). This is the case that ss->thread == MACH_PORT_NULL, that -is, a global signal. In the main thread, between __proc_dostop and -__task_create is the __thread_abort call on the signal thread which would -abort any current kernel operation (but leave ss locked). Later in fork, -in the parent, when _hurd_siglock is unlocked in fork, the parent's -signal thread can proceed and will unlock eventually the global sigstate. -In the client, _hurd_siglock will likewise be unlocked, but the global -sigstate never will be, as the client's signal thread has been configured -to restart execution from _hurd_msgport_receive. Thus, when the child -tries to unlock ss' critical section lock at the end of fork, it will -first lock the global sigstate, will spin trying to lock it, which can -never be successful, and we get our deadlock. - -Options seem to be: - - * Move the locking of _hurd_siglock earlier in post_signal -- but that - may generally impact performance, if this locking isn't generally - needed anyway? - - On the other hand, would it actually make sense to wait here until we - are not any longer in a critical section (which is meant to disable - signal delivery anway (but not for preempted signals?))? - - * Clear the global sigstate in the fork's child with the rationale that - we're anyway restarting the signal thread from a clean state. This - has now been implemented. - -Why has this problem not been observed before Jérémie's patches? (Or has -it? Perhaps even more rarely?) In _S_msg_sig_post, the signal is now -posted to a *global receiver thread*, whereas previously it was posted to -the *designated signal-receiving thread*. The latter one was in a -critical section in fork, so didn't try to handle the signal until after -leaving the critical section? (Not completely analyzed and verified.) - -Another question is what the signal is that is being received -during/around the time __proc_dostop executes. +From: Richard Braun +Subject: [PATCH] Hurd: make sigstates hold a reference on thread ports + +This change is required in order to correctly release per-thread +resources. Directly reusing the threading library reference isn't +possible since the sigstate is also used early in the main thread, +before threading is initialized. + +* hurd/hurd/signal.h (_hurd_self_sigstate): Drop thread reference after +calling _hurd_thread_sigstate. +(_hurd_critical_section_lock): Likewise. +* hurd/hurdsig.c (_hurd_thread_sigstate): Add a reference on the thread. +(_hurd_sigstate_delete): Drop thread reference. diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index db60e6f0a1..1d1218a88a 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -64,7 +64,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 +120,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); @@ -161,7 +165,11 @@ _hurd_self_sigstate (void) struct hurd_sigstate **location = (void *) __hurd_threadvar_location (_HURD_THREADVAR_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; } @@ -192,11 +200,14 @@ _hurd_critical_section_lock (void) struct 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 way; this locks the sigstate lock. */ - ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); + ss = *location = _hurd_thread_sigstate (self); + __mach_port_deallocate (__mach_task_self (), self); __spin_unlock (&ss->lock); } diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 72c582f00b..486be7ca9d 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -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. */ -- cgit v1.2.3 From ba5dfaef3a8eceb111a363d9505b5f12bbbf451b Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 4 Jan 2014 18:12:37 +0100 Subject: hurdselect: remove dead code. This removes code which actually never happens, and is already taken care of in the function. This is in the second part of select, when the __mach_msg() function over the portset has returned something else than MACH_MSG_SUCCESS. I guess in the past the value returned by __mach_msg() was stored in err, so this code was necessary to set back err to 0, but now it is stored in msgerr, so err is already still 0 by default. It can thus never contain MACH_RCV_TIMED_OUT, i.e. the code is dead. The first case mentioned in the comment is already handled: on time out with no message, err is already still the default 0. On time out due to poll, err would still be 0, unless some of the io_select RPCs has returned EINTR, in which case it contains EINTR. If any other io_select RPCs had returned a proper answer, got!=0, and thus err is set to 0 just below. The code is thus indeed not useful any more. * hurd/hurdselect.c (_hurd_select): Remove unreachable check for MACH_RCV_TIMED_OUT. Signed-off-by: Samuel Thibault --- .topdeps | 2 +- .topmsg | 31 +++++++++++++++++++------------ hurd/hurdselect.c | 8 -------- 3 files changed, 20 insertions(+), 21 deletions(-) (limited to 'hurd') diff --git a/.topdeps b/.topdeps index e7a14c6ca9..180b47c18b 100644 --- a/.topdeps +++ b/.topdeps @@ -1 +1 @@ -0323d08657f111267efa47bd448fbf6cd76befe8 +baseline diff --git a/.topmsg b/.topmsg index dd6634c886..97fc0192e1 100644 --- a/.topmsg +++ b/.topmsg @@ -1,16 +1,23 @@ -Subject: Baseline for our topic branches. +From: Samuel Thibault +Subject: [PATCH] hurdselect: remove dead code. ---- +This removes code which actually never happens, and is already taken +care of in the function. -This need not strictly be a TopGit branch, but it is for easy synchronization -between different machines. +This is in the second part of select, when the __mach_msg() function +over the portset has returned something else than MACH_MSG_SUCCESS. I +guess in the past the value returned by __mach_msg() was stored in err, +so this code was necessary to set back err to 0, but now it is stored in +msgerr, so err is already still 0 by default. It can thus never contain +MACH_RCV_TIMED_OUT, i.e. the code is dead. The first case mentioned in +the comment is already handled: on time out with no message, err is +already still the default 0. On time out due to poll, err would still be +0, unless some of the io_select RPCs has returned EINTR, in which case +it contains EINTR. If any other io_select RPCs had returned a proper +answer, got!=0, and thus err is set to 0 just below. The code is thus +indeed not useful any more. -As the baseline is merged into the topic branches, it is forward-only. +* hurd/hurdselect.c (_hurd_select): Remove unreachable check for +MACH_RCV_TIMED_OUT. -To advance it: - - $ echo [SHA1] > .topdeps - $ git commit -m Advance. -- .topdeps - $ tg update - ---- +Signed-off-by: Samuel Thibault diff --git a/hurd/hurdselect.c b/hurd/hurdselect.c index 4544cb753b..859b351032 100644 --- a/hurd/hurdselect.c +++ b/hurd/hurdselect.c @@ -407,14 +407,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 (got) /* At least one descriptor is known to be ready now, so we will return success. */ -- cgit v1.2.3 From ba42395e4120e703cc2b666b6c035989eb7e940a Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 22 Apr 2014 00:38:57 +0200 Subject: Also avoid inlining when NOT_IN_libc is defined --- hurd/hurd/fd.h | 2 +- hurd/hurd/port.h | 12 ++++++------ hurd/hurd/signal.h | 6 +++--- hurd/hurd/threadvar.h | 4 ++-- hurd/hurd/userlink.h | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'hurd') diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h index cd8edccdc2..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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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 ce55154364..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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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 ae581f68b2..e3e2790a98 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -129,7 +129,7 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void) #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline #endif -#if defined __USE_EXTERN_INLINES && defined _LIBC +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { @@ -168,7 +168,7 @@ extern int _hurd_core_limit; void *_hurd_critical_section_lock (void); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_SIGNAL_H_EXTERN_INLINE void * _hurd_critical_section_lock (void) { @@ -198,7 +198,7 @@ _hurd_critical_section_lock (void) void _hurd_critical_section_unlock (void *our_lock); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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 e8013ce03f..93e91ecbb5 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -82,7 +82,7 @@ enum __hurd_threadvar_index extern unsigned long int *__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, void *__sp); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * __hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, void *__sp) @@ -108,7 +108,7 @@ __hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW the same stack frame by different threads. */ __attribute__ ((__const__)); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * __hurd_threadvar_location (enum __hurd_threadvar_index __index) { diff --git a/hurd/hurd/userlink.h b/hurd/hurd/userlink.h index 4962f0cb65..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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#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); -#if defined __USE_EXTERN_INLINES && defined _LIBC +#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc _HURD_USERLINK_H_EXTERN_INLINE int _hurd_userlink_clear (struct hurd_userlink **chainp) { -- cgit v1.2.3 From 1cefd2a2f2ebdd72f2e12f14a98e07f0da25dde3 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 22 Apr 2014 00:43:09 +0200 Subject: Rather keep _hurd_sigstate in tcbhead_t it avoids involving all the TLS stuff while handling signals... --- .topmsg | 2 +- hurd/hurd/signal.h | 11 +++++------ hurd/hurdsig.c | 3 --- sysdeps/mach/hurd/Versions | 2 -- sysdeps/mach/hurd/tls.h | 1 + 5 files changed, 7 insertions(+), 12 deletions(-) (limited to 'hurd') diff --git a/.topmsg b/.topmsg index 5bb20d2704..cdf5ad38b5 100644 --- a/.topmsg +++ b/.topmsg @@ -4,4 +4,4 @@ Subject: [PATCH] tls-threadvar replace the custom threadvar mechanism with generic TLS. That will fix sigaltstack. -Note: the added reply_port field should be kept last. +Note: the added reply_port and _hurd_sigstate fields should be kept last. diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index e633debe7c..dcb7f2162b 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -128,14 +128,13 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void) #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline #endif -extern __thread struct hurd_sigstate *_hurd_sigstate; #if defined __USE_EXTERN_INLINES && defined _LIBC _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { - if (_hurd_sigstate == NULL) - _hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); - return _hurd_sigstate; + if (THREAD_SELF->_hurd_sigstate == NULL) + THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + return THREAD_SELF->_hurd_sigstate; } #endif @@ -178,14 +177,14 @@ _hurd_critical_section_lock (void) return NULL; #endif - ss = _hurd_sigstate; + ss = THREAD_SELF->_hurd_sigstate; if (ss == NULL) { /* 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 way; this locks the sigstate lock. */ - ss = _hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + ss = THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); __spin_unlock (&ss->lock); } diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 1d87e2e973..80eac9f998 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -50,9 +50,6 @@ thread_t _hurd_sigthread; unsigned long int __hurd_sigthread_stack_base; unsigned long int __hurd_sigthread_stack_end; -/* Per-thread signal state. */ -__thread struct hurd_sigstate *_hurd_sigstate; - /* Linked-list of per-thread signal state. */ struct hurd_sigstate *_hurd_sigstates; diff --git a/sysdeps/mach/hurd/Versions b/sysdeps/mach/hurd/Versions index 9ecdbaf90e..62ee990ac1 100644 --- a/sysdeps/mach/hurd/Versions +++ b/sysdeps/mach/hurd/Versions @@ -7,7 +7,6 @@ libc { # Functions shared with the dynamic linker __libc_read; __libc_write; __libc_lseek64; __libc_lock_self0; __libc_lock_self; - _hurd_sigstate; _dl_init_first; } @@ -34,6 +33,5 @@ ld { # functions that must be shared with libc __libc_read; __libc_write; __libc_lseek64; __libc_lock_self0; __libc_lock_self; - _hurd_sigstate; } } diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h index a6ac16b6ba..73f495a8a1 100644 --- a/sysdeps/mach/hurd/tls.h +++ b/sysdeps/mach/hurd/tls.h @@ -50,6 +50,7 @@ typedef struct /* Keep this field last */ mach_port_t reply_port; /* This thread's reply port. */ + struct hurd_sigstate *_hurd_sigstate; } tcbhead_t; -- cgit v1.2.3 From b8198bf5e16c23c074ddc9fa40931c9c9bf7b722 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 22 Apr 2014 16:14:31 +0200 Subject: Optimize _hurd_sigstate access --- hurd/hurd/signal.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'hurd') diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index 7a56950023..1e3e93be0c 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -132,9 +132,10 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void) _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { - if (THREAD_SELF->_hurd_sigstate == NULL) - THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); - return THREAD_SELF->_hurd_sigstate; + struct hurd_sigstate **location = &THREAD_SELF->_hurd_sigstate; + if (*location == NULL) + *location = _hurd_thread_sigstate (__mach_thread_self ()); + return *location; } #endif @@ -169,6 +170,7 @@ void *_hurd_critical_section_lock (void); _HURD_SIGNAL_H_EXTERN_INLINE void * _hurd_critical_section_lock (void) { + struct hurd_sigstate **location; struct hurd_sigstate *ss; #ifdef __LIBC_NO_TLS @@ -177,14 +179,15 @@ _hurd_critical_section_lock (void) return NULL; #endif - ss = THREAD_SELF->_hurd_sigstate; + location = &THREAD_SELF->_hurd_sigstate; + ss = *location; if (ss == NULL) { /* 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 way; this locks the sigstate lock. */ - ss = THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); __spin_unlock (&ss->lock); } -- cgit v1.2.3 From adb9c13ccfa6cba955c7700c9277f1e274ce3b8e Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 27 Aug 2014 21:47:10 +0200 Subject: remove two more bogus assertions, and add explanations --- .topmsg | 17 ++++++++++++++++- hurd/hurdexec.c | 1 - hurd/thread-cancel.c | 1 - 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'hurd') diff --git a/.topmsg b/.topmsg index 629fe0f139..f59330bd62 100644 --- a/.topmsg +++ b/.topmsg @@ -1,7 +1,22 @@ From: Samuel Thibault Subject: [PATCH] The critical section lock _can_ be held in these place. -At least since hurd_thread_cancel can be called by another thread. +At least since hurd_thread_cancel can be called by another thread and lock our +critical lock. + +http://bugs.debian.org/46859 + +“ +Thomas suggested that there is no need to take the critical section +lock. I believe that taking the critical section lock is necessary to +prevent the target thread from entering a signal handler. Roland will +look into the problem. +” + +Taking the critical section lock makes these assertions bogus. + +It happens that hurd_thread_cancel is only called from libports and inside +/hurd/term so this is rare in practice. 2006-08-05 Samuel Thibault diff --git a/hurd/hurdexec.c b/hurd/hurdexec.c index 0ced7f32b4..1de90c0bc2 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); __spin_lock (&ss->lock); 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); -- cgit v1.2.3 From c30b727f51a9678663788810a4ab0eb4b18071d4 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 12 Oct 2014 21:36:07 +0200 Subject: Fix incorrect ready counting. Using SELECT_ALL would make the fd counting thrice, and not only once per presence in select masks. --- hurd/hurdselect.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'hurd') diff --git a/hurd/hurdselect.c b/hurd/hurdselect.c index bb942429dd..95dfde059b 100644 --- a/hurd/hurdselect.c +++ b/hurd/hurdselect.c @@ -548,7 +548,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++; -- cgit v1.2.3