Mercurial > illumos > illumos-gate
changeset 10637:f6eac4af74a8
6881066 sporadic hang of thr_suspend
author | Roger A. Faulkner <Roger.Faulkner@Sun.COM> |
---|---|
date | Thu, 24 Sep 2009 05:17:17 -0700 |
parents | 4068d6e64f8c |
children | 5d19a597329d |
files | usr/src/cmd/mdb/common/modules/libc/libc.c usr/src/lib/libc/inc/thr_uberdata.h usr/src/lib/libc/port/threads/rwlock.c usr/src/lib/libc/port/threads/synch.c usr/src/lib/libc/port/threads/thr.c |
diffstat | 5 files changed, 42 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/modules/libc/libc.c Thu Sep 24 07:49:36 2009 -0400 +++ b/usr/src/cmd/mdb/common/modules/libc/libc.c Thu Sep 24 05:17:17 2009 -0700 @@ -583,13 +583,14 @@ ulwp.ul_td_evbuf.eventnum, prt_addr(ulwp.ul_td_evbuf.eventdata, 0)); - HD("td'enable sync'reg qtype cv_wake usropts"); - mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d ", + HD("td'enable sync'reg qtype cv_wake rtld usropts"); + mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d ", OFFSET(ul_td_events_enable), ulwp.ul_td_events_enable, ulwp.ul_sync_obj_reg, ulwp.ul_qtype, - ulwp.ul_cv_wake); + ulwp.ul_cv_wake, + ulwp.ul_rtld); mdb_printf(ulwp.ul_usropts? "0x%x\n" : "%d\n", ulwp.ul_usropts);
--- a/usr/src/lib/libc/inc/thr_uberdata.h Thu Sep 24 07:49:36 2009 -0400 +++ b/usr/src/lib/libc/inc/thr_uberdata.h Thu Sep 24 05:17:17 2009 -0700 @@ -609,6 +609,7 @@ char ul_sync_obj_reg; /* tdb_sync_obj_register() */ char ul_qtype; /* MX or CV */ char ul_cv_wake; /* != 0: just wake up, don't requeue */ + int ul_rtld; /* thread is running inside ld.so.1 */ int ul_usropts; /* flags given to thr_create() */ void *(*ul_startpc)(void *); /* start func (thr_create()) */ void *ul_startarg; /* argument for start function */ @@ -1021,6 +1022,7 @@ char ul_sync_obj_reg; /* tdb_sync_obj_register() */ char ul_qtype; /* MX or CV */ char ul_cv_wake; /* != 0: just wake up, don't requeue */ + int ul_rtld; /* thread is running inside ld.so.1 */ int ul_usropts; /* flags given to thr_create() */ caddr32_t ul_startpc; /* start func (thr_create()) */ caddr32_t ul_startarg; /* argument for start function */ @@ -1254,7 +1256,10 @@ * of the signal mask must also be deferred. */ #define sigoff(self) (self->ul_sigdefer++) -extern void sigon(ulwp_t *); +#define sigon(self) \ + (void) ((--self->ul_sigdefer == 0 && \ + self->ul_curplease && self->ul_critical == 0)? \ + (do_exit_critical(), 0) : 0) /* these are exported functions */ extern void _sigoff(void);
--- a/usr/src/lib/libc/port/threads/rwlock.c Thu Sep 24 07:49:36 2009 -0400 +++ b/usr/src/lib/libc/port/threads/rwlock.c Thu Sep 24 05:17:17 2009 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -239,13 +239,15 @@ int rwlock_destroy(rwlock_t *rwlp) { + ulwp_t *self = curthread; + /* * Once destroyed, we can no longer be holding a read or write lock. * We can do nothing about other threads that are holding read locks. */ - sigoff(curthread); + sigoff(self); rwl_entry(rwlp)->rd_count = 0; - sigon(curthread); + sigon(self); rwlp->rwlock_magic = 0; tdb_sync_obj_deregister(rwlp); return (0);
--- a/usr/src/lib/libc/port/threads/synch.c Thu Sep 24 07:49:36 2009 -0400 +++ b/usr/src/lib/libc/port/threads/synch.c Thu Sep 24 05:17:17 2009 -0700 @@ -2670,25 +2670,30 @@ void sig_mutex_lock(mutex_t *mp) { - sigoff(curthread); + ulwp_t *self = curthread; + + sigoff(self); (void) mutex_lock(mp); } void sig_mutex_unlock(mutex_t *mp) { + ulwp_t *self = curthread; + (void) mutex_unlock(mp); - sigon(curthread); + sigon(self); } int sig_mutex_trylock(mutex_t *mp) { + ulwp_t *self = curthread; int error; - sigoff(curthread); + sigoff(self); if ((error = mutex_trylock(mp)) != 0) - sigon(curthread); + sigon(self); return (error); }
--- a/usr/src/lib/libc/port/threads/thr.c Thu Sep 24 07:49:36 2009 -0400 +++ b/usr/src/lib/libc/port/threads/thr.c Thu Sep 24 05:17:17 2009 -0700 @@ -1785,8 +1785,8 @@ } /* - * Suspend an lwp with lwp_suspend(), then move it to a safe - * point, that is, to a point where ul_critical is zero. + * Suspend an lwp with lwp_suspend(), then move it to a safe point, + * that is, to a point where ul_critical and ul_rtld are both zero. * On return, the ulwp_lock() is dropped as with ulwp_unlock(). * If 'link_dropped' is non-NULL, then 'link_lock' is held on entry. * If we have to drop link_lock, we store 1 through link_dropped. @@ -1823,7 +1823,8 @@ spin_lock_clear(&ulwp->ul_spinlock); top: - if (ulwp->ul_critical == 0 || ulwp->ul_stopping) { + if ((ulwp->ul_critical == 0 && ulwp->ul_rtld == 0) || + ulwp->ul_stopping) { /* thread is already safe */ ulwp->ul_stop |= whystopped; } else { @@ -2147,6 +2148,7 @@ /* * Exit a critical section, take deferred actions if necessary. + * Called from exit_critical() and from sigon(). */ void do_exit_critical() @@ -2155,7 +2157,12 @@ int sig; ASSERT(self->ul_critical == 0); - if (self->ul_dead) + + /* + * Don't suspend ourself or take a deferred signal while dying + * or while executing inside the dynamic linker (ld.so.1). + */ + if (self->ul_dead || self->ul_rtld) return; while (self->ul_pleasestop || @@ -2214,6 +2221,7 @@ self->ul_bindflags |= bindflag; if ((flags & (THR_FLG_NOLOCK | THR_FLG_REENTER)) == THR_FLG_NOLOCK) { sigoff(self); /* see no signals while holding ld_lock */ + self->ul_rtld++; /* don't suspend while in ld.so.1 */ (void) mutex_lock(&udp->ld_lock); } enter_critical(self); @@ -2239,6 +2247,7 @@ if ((flags & (THR_FLG_NOLOCK | THR_FLG_REENTER)) == THR_FLG_NOLOCK) { if (MUTEX_OWNED(&udp->ld_lock, self)) { (void) mutex_unlock(&udp->ld_lock); + self->ul_rtld--; sigon(self); /* reenable signals */ } } @@ -2275,28 +2284,18 @@ void _sigoff(void) { - sigoff(curthread); + ulwp_t *self = curthread; + + sigoff(self); } void _sigon(void) { - sigon(curthread); -} - -void -sigon(ulwp_t *self) -{ - int sig; + ulwp_t *self = curthread; ASSERT(self->ul_sigdefer > 0); - if (--self->ul_sigdefer == 0) { - if ((sig = self->ul_cursig) != 0 && self->ul_critical == 0) { - self->ul_cursig = 0; - take_deferred_signal(sig); - ASSERT(self->ul_cursig == 0); - } - } + sigon(self); } int