diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/os/exec.c | 24 | ||||
-rw-r--r-- | usr/src/uts/common/os/exit.c | 18 | ||||
-rw-r--r-- | usr/src/uts/common/os/fork.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/os/lwp.c | 200 | ||||
-rw-r--r-- | usr/src/uts/common/os/main.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/sys/proc.h | 27 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/lwpsys.c | 48 |
7 files changed, 259 insertions, 68 deletions
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c index 9b3dce476a..2ca011f17b 100644 --- a/usr/src/uts/common/os/exec.c +++ b/usr/src/uts/common/os/exec.c @@ -130,11 +130,12 @@ exec_common(const char *fname, const char **argp, const char **envp, struct execa ua; k_sigset_t savedmask; lwpdir_t *lwpdir = NULL; - lwpdir_t **tidhash; + tidhash_t *tidhash; lwpdir_t *old_lwpdir = NULL; uint_t old_lwpdir_sz; - lwpdir_t **old_tidhash; + tidhash_t *old_tidhash; uint_t old_tidhash_sz; + ret_tidhash_t *ret_tidhash; lwpent_t *lep; boolean_t brandme = B_FALSE; @@ -416,7 +417,7 @@ exec_common(const char *fname, const char **argp, const char **envp, if (curthread->t_tid != 1 || p->p_lwpdir_sz != 2) { lwpdir = kmem_zalloc(2 * sizeof (lwpdir_t), KM_SLEEP); lwpdir->ld_next = lwpdir + 1; - tidhash = kmem_zalloc(2 * sizeof (lwpdir_t *), KM_SLEEP); + tidhash = kmem_zalloc(2 * sizeof (tidhash_t), KM_SLEEP); if (p->p_lwpdir != NULL) lep = p->p_lwpdir[curthread->t_dslot].ld_entry; else @@ -461,13 +462,15 @@ exec_common(const char *fname, const char **argp, const char **envp, old_tidhash_sz = p->p_tidhash_sz; p->p_lwpdir = p->p_lwpfree = lwpdir; p->p_lwpdir_sz = 2; - p->p_tidhash = tidhash; - p->p_tidhash_sz = 2; lep->le_thread = curthread; lep->le_lwpid = curthread->t_tid; lep->le_start = curthread->t_start; - lwp_hash_in(p, lep); + lwp_hash_in(p, lep, tidhash, 2, 0); + p->p_tidhash = tidhash; + p->p_tidhash_sz = 2; } + ret_tidhash = p->p_ret_tidhash; + p->p_ret_tidhash = NULL; /* * Restore the saved signal mask and @@ -478,7 +481,14 @@ exec_common(const char *fname, const char **argp, const char **envp, mutex_exit(&p->p_lock); if (old_lwpdir) { kmem_free(old_lwpdir, old_lwpdir_sz * sizeof (lwpdir_t)); - kmem_free(old_tidhash, old_tidhash_sz * sizeof (lwpdir_t *)); + kmem_free(old_tidhash, old_tidhash_sz * sizeof (tidhash_t)); + } + while (ret_tidhash != NULL) { + ret_tidhash_t *next = ret_tidhash->rth_next; + kmem_free(ret_tidhash->rth_tidhash, + ret_tidhash->rth_tidhash_sz * sizeof (tidhash_t)); + kmem_free(ret_tidhash, sizeof (*ret_tidhash)); + ret_tidhash = next; } ASSERT(error == 0); diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c index 02f7c5931f..bd2991c393 100644 --- a/usr/src/uts/common/os/exit.c +++ b/usr/src/uts/common/os/exit.c @@ -20,14 +20,12 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -#pragma ident "%Z%%M% %I% %E% SMI" /* from SVr4.0 1.74 */ - #include <sys/types.h> #include <sys/param.h> #include <sys/sysmacros.h> @@ -341,8 +339,9 @@ proc_exit(int why, int what) sigqueue_t *sqp; lwpdir_t *lwpdir; uint_t lwpdir_sz; - lwpdir_t **tidhash; + tidhash_t *tidhash; uint_t tidhash_sz; + ret_tidhash_t *ret_tidhash; refstr_t *cwd; hrtime_t hrutime, hrstime; int evaporate; @@ -779,11 +778,13 @@ proc_exit(int why, int what) lwpdir_sz = p->p_lwpdir_sz; tidhash = p->p_tidhash; tidhash_sz = p->p_tidhash_sz; + ret_tidhash = p->p_ret_tidhash; p->p_lwpdir = NULL; p->p_lwpfree = NULL; p->p_lwpdir_sz = 0; p->p_tidhash = NULL; p->p_tidhash_sz = 0; + p->p_ret_tidhash = NULL; /* * If the process has context ops installed, call the exit routine @@ -855,7 +856,14 @@ proc_exit(int why, int what) task_rele(tk); kmem_free(lwpdir, lwpdir_sz * sizeof (lwpdir_t)); - kmem_free(tidhash, tidhash_sz * sizeof (lwpdir_t *)); + kmem_free(tidhash, tidhash_sz * sizeof (tidhash_t)); + while (ret_tidhash != NULL) { + ret_tidhash_t *next = ret_tidhash->rth_next; + kmem_free(ret_tidhash->rth_tidhash, + ret_tidhash->rth_tidhash_sz * sizeof (tidhash_t)); + kmem_free(ret_tidhash, sizeof (*ret_tidhash)); + ret_tidhash = next; + } lwp_pcb_exit(); diff --git a/usr/src/uts/common/os/fork.c b/usr/src/uts/common/os/fork.c index fd4972f6d7..524f0f0aaf 100644 --- a/usr/src/uts/common/os/fork.c +++ b/usr/src/uts/common/os/fork.c @@ -374,7 +374,7 @@ cfork(int isvfork, int isfork1, int flags) ldp->ld_next = ldp + 1; cp->p_tidhash_sz = (cp->p_lwpdir_sz + 2) / 2; cp->p_tidhash = - kmem_zalloc(cp->p_tidhash_sz * sizeof (lwpdir_t *), KM_SLEEP); + kmem_zalloc(cp->p_tidhash_sz * sizeof (tidhash_t), KM_SLEEP); /* * Duplicate parent's lwps. @@ -430,7 +430,8 @@ cfork(int isvfork, int isfork1, int flags) clep = kmem_zalloc(sizeof (*clep), KM_SLEEP); clep->le_lwpid = lep->le_lwpid; clep->le_start = lep->le_start; - lwp_hash_in(cp, clep); + lwp_hash_in(cp, clep, + cp->p_tidhash, cp->p_tidhash_sz, 0); } } } diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c index d80f32c658..a4bc1bffd2 100644 --- a/usr/src/uts/common/os/lwp.c +++ b/usr/src/uts/common/os/lwp.c @@ -20,12 +20,10 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/param.h> #include <sys/types.h> #include <sys/sysmacros.h> @@ -60,6 +58,9 @@ #include <sys/cmn_err.h> #include <sys/brand.h> +/* hash function for the lwpid hash table, p->p_tidhash[] */ +#define TIDHASH(tid, hash_sz) ((tid) & ((hash_sz) - 1)) + void *segkp_lwp; /* cookie for pool of segkp resources */ extern void reapq_move_lq_to_tq(kthread_t *); extern void freectx_ctx(struct ctxop *); @@ -85,8 +86,9 @@ lwp_create(void (*proc)(), caddr_t arg, size_t len, proc_t *p, lwpent_t *lep; lwpdir_t *old_dir = NULL; uint_t old_dirsz = 0; - lwpdir_t **old_hash = NULL; + tidhash_t *old_hash = NULL; uint_t old_hashsz = 0; + ret_tidhash_t *ret_tidhash = NULL; int i; int rctlfail = 0; boolean_t branded = 0; @@ -232,31 +234,58 @@ grow: * which leads to these hash table sizes corresponding to * the above directory sizes: * 2, 4, 8, 16, 32, 64, 128, 256, 512, ... + * A note on growing the hash table: + * For performance reasons, code in lwp_unpark() does not + * acquire curproc->p_lock when searching the hash table. + * Rather, it calls lwp_hash_lookup_and_lock() which + * acquires only the individual hash bucket lock, taking + * care to deal with reallocation of the hash table + * during the time it takes to acquire the lock. + * + * This is sufficient to protect the integrity of the + * hash table, but it requires us to acquire all of the + * old hash bucket locks before growing the hash table + * and to release them afterwards. It also requires us + * not to free the old hash table because some thread + * in lwp_hash_lookup_and_lock() might still be trying + * to acquire the old bucket lock. + * + * So we adopt the tactic of keeping all of the retired + * hash tables on a linked list, so they can be safely + * freed when the process exits or execs. + * + * Because the hash table grows in powers of two, the + * total size of all of the hash tables will be slightly + * less than twice the size of the largest hash table. */ while (p->p_lwpfree == NULL) { uint_t dirsz = p->p_lwpdir_sz; - uint_t new_dirsz; - uint_t new_hashsz; lwpdir_t *new_dir; + uint_t new_dirsz; lwpdir_t *ldp; - lwpdir_t **new_hash; + tidhash_t *new_hash; + uint_t new_hashsz; mutex_exit(&p->p_lock); - if (old_dir != NULL) { + /* + * Prepare to remember the old p_tidhash for later + * kmem_free()ing when the process exits or execs. + */ + if (ret_tidhash == NULL) + ret_tidhash = kmem_zalloc(sizeof (ret_tidhash_t), + KM_SLEEP); + if (old_dir != NULL) kmem_free(old_dir, old_dirsz * sizeof (*old_dir)); + if (old_hash != NULL) kmem_free(old_hash, old_hashsz * sizeof (*old_hash)); - old_dir = NULL; - old_dirsz = 0; - old_hash = NULL; - old_hashsz = 0; - } + new_dirsz = 2 * dirsz + 2; new_dir = kmem_zalloc(new_dirsz * sizeof (lwpdir_t), KM_SLEEP); for (ldp = new_dir, i = 1; i < new_dirsz; i++, ldp++) ldp->ld_next = ldp + 1; new_hashsz = (new_dirsz + 2) / 2; - new_hash = kmem_zalloc(new_hashsz * sizeof (lwpdir_t *), + new_hash = kmem_zalloc(new_hashsz * sizeof (tidhash_t), KM_SLEEP); mutex_enter(&p->p_lock); @@ -273,15 +302,20 @@ grow: old_hash = new_hash; old_hashsz = new_hashsz; } else { - old_dir = p->p_lwpdir; - old_dirsz = p->p_lwpdir_sz; + /* + * For the benefit of lwp_hash_lookup_and_lock(), + * called from lwp_unpark(), which searches the + * tid hash table without acquiring p->p_lock, + * we must acquire all of the tid hash table + * locks before replacing p->p_tidhash. + */ old_hash = p->p_tidhash; old_hashsz = p->p_tidhash_sz; - p->p_lwpdir = new_dir; - p->p_lwpfree = new_dir; - p->p_lwpdir_sz = new_dirsz; - p->p_tidhash = new_hash; - p->p_tidhash_sz = new_hashsz; + for (i = 0; i < old_hashsz; i++) { + mutex_enter(&old_hash[i].th_lock); + mutex_enter(&new_hash[i].th_lock); + } + /* * We simply hash in all of the old directory entries. * This works because the old directory has no empty @@ -289,11 +323,57 @@ grow: * This reproduces the original directory ordering * (required for /proc directory semantics). */ - for (ldp = old_dir, i = 0; i < dirsz; i++, ldp++) - lwp_hash_in(p, ldp->ld_entry); + old_dir = p->p_lwpdir; + old_dirsz = p->p_lwpdir_sz; + p->p_lwpdir = new_dir; + p->p_lwpfree = new_dir; + p->p_lwpdir_sz = new_dirsz; + for (ldp = old_dir, i = 0; i < old_dirsz; i++, ldp++) + lwp_hash_in(p, ldp->ld_entry, + new_hash, new_hashsz, 0); + + /* + * Remember the old hash table along with all + * of the previously-remembered hash tables. + * We will free them at process exit or exec. + */ + ret_tidhash->rth_tidhash = old_hash; + ret_tidhash->rth_tidhash_sz = old_hashsz; + ret_tidhash->rth_next = p->p_ret_tidhash; + p->p_ret_tidhash = ret_tidhash; + /* - * Defer freeing memory until we drop p->p_lock, + * Now establish the new tid hash table. + * As soon as we assign p->p_tidhash, + * code in lwp_unpark() can start using it. */ + membar_producer(); + p->p_tidhash = new_hash; + + /* + * It is necessary that p_tidhash reach global + * visibility before p_tidhash_sz. Otherwise, + * code in lwp_hash_lookup_and_lock() could + * index into the old p_tidhash using the new + * p_tidhash_sz and thereby access invalid data. + */ + membar_producer(); + p->p_tidhash_sz = new_hashsz; + + /* + * Release the locks; allow lwp_unpark() to carry on. + */ + for (i = 0; i < old_hashsz; i++) { + mutex_exit(&old_hash[i].th_lock); + mutex_exit(&new_hash[i].th_lock); + } + + /* + * Avoid freeing these objects below. + */ + ret_tidhash = NULL; + old_hash = NULL; + old_hashsz = 0; } } @@ -550,7 +630,7 @@ grow: lep->le_thread = t; lep->le_lwpid = t->t_tid; lep->le_start = t->t_start; - lwp_hash_in(p, lep); + lwp_hash_in(p, lep, p->p_tidhash, p->p_tidhash_sz, 1); if (state == TS_RUN) { /* @@ -604,10 +684,12 @@ error: mutex_exit(&p->p_lock); } - if (old_dir != NULL) { + if (old_dir != NULL) kmem_free(old_dir, old_dirsz * sizeof (*old_dir)); + if (old_hash != NULL) kmem_free(old_hash, old_hashsz * sizeof (*old_hash)); - } + if (ret_tidhash != NULL) + kmem_free(ret_tidhash, sizeof (ret_tidhash_t)); DTRACE_PROC1(lwp__create, kthread_t *, t); return (lwp); @@ -1742,8 +1824,10 @@ retry: * Add a new lwp entry to the lwp directory and to the lwpid hash table. */ void -lwp_hash_in(proc_t *p, lwpent_t *lep) +lwp_hash_in(proc_t *p, lwpent_t *lep, tidhash_t *tidhash, uint_t tidhash_sz, + int do_lock) { + tidhash_t *thp = &tidhash[TIDHASH(lep->le_lwpid, tidhash_sz)]; lwpdir_t **ldpp; lwpdir_t *ldp; kthread_t *t; @@ -1757,10 +1841,13 @@ lwp_hash_in(proc_t *p, lwpent_t *lep) ASSERT(ldp->ld_entry == NULL); ldp->ld_entry = lep; + if (do_lock) + mutex_enter(&thp->th_lock); + /* * Insert it into the lwpid hash table. */ - ldpp = &p->p_tidhash[TIDHASH(p, lep->le_lwpid)]; + ldpp = &thp->th_list; ldp->ld_next = *ldpp; *ldpp = ldp; @@ -1771,6 +1858,9 @@ lwp_hash_in(proc_t *p, lwpent_t *lep) ASSERT(lep->le_lwpid == t->t_tid); t->t_dslot = (int)(ldp - p->p_lwpdir); } + + if (do_lock) + mutex_exit(&thp->th_lock); } /* @@ -1782,11 +1872,13 @@ lwp_hash_in(proc_t *p, lwpent_t *lep) void lwp_hash_out(proc_t *p, id_t lwpid) { + tidhash_t *thp = &p->p_tidhash[TIDHASH(lwpid, p->p_tidhash_sz)]; lwpdir_t **ldpp; lwpdir_t *ldp; lwpent_t *lep; - for (ldpp = &p->p_tidhash[TIDHASH(p, lwpid)]; + mutex_enter(&thp->th_lock); + for (ldpp = &thp->th_list; (ldp = *ldpp) != NULL; ldpp = &ldp->ld_next) { lep = ldp->ld_entry; if (lep->le_lwpid == lwpid) { @@ -1799,6 +1891,7 @@ lwp_hash_out(proc_t *p, id_t lwpid) break; } } + mutex_exit(&thp->th_lock); } /* @@ -1807,6 +1900,7 @@ lwp_hash_out(proc_t *p, id_t lwpid) lwpdir_t * lwp_hash_lookup(proc_t *p, id_t lwpid) { + tidhash_t *thp; lwpdir_t *ldp; /* @@ -1817,8 +1911,8 @@ lwp_hash_lookup(proc_t *p, id_t lwpid) if (p->p_tidhash == NULL) return (NULL); - for (ldp = p->p_tidhash[TIDHASH(p, lwpid)]; - ldp != NULL; ldp = ldp->ld_next) { + thp = &p->p_tidhash[TIDHASH(lwpid, p->p_tidhash_sz)]; + for (ldp = thp->th_list; ldp != NULL; ldp = ldp->ld_next) { if (ldp->ld_entry->le_lwpid == lwpid) return (ldp); } @@ -1827,6 +1921,48 @@ lwp_hash_lookup(proc_t *p, id_t lwpid) } /* + * Same as lwp_hash_lookup(), but acquire and return + * the tid hash table entry lock on success. + */ +lwpdir_t * +lwp_hash_lookup_and_lock(proc_t *p, id_t lwpid, kmutex_t **mpp) +{ + tidhash_t *tidhash; + uint_t tidhash_sz; + tidhash_t *thp; + lwpdir_t *ldp; + +top: + tidhash_sz = p->p_tidhash_sz; + membar_consumer(); + if ((tidhash = p->p_tidhash) == NULL) + return (NULL); + + thp = &tidhash[TIDHASH(lwpid, tidhash_sz)]; + mutex_enter(&thp->th_lock); + + /* + * Since we are not holding p->p_lock, the tid hash table + * may have changed. If so, start over. If not, then + * it cannot change until after we drop &thp->th_lock; + */ + if (tidhash != p->p_tidhash || tidhash_sz != p->p_tidhash_sz) { + mutex_exit(&thp->th_lock); + goto top; + } + + for (ldp = thp->th_list; ldp != NULL; ldp = ldp->ld_next) { + if (ldp->ld_entry->le_lwpid == lwpid) { + *mpp = &thp->th_lock; + return (ldp); + } + } + + mutex_exit(&thp->th_lock); + return (NULL); +} + +/* * Update the indicated LWP usage statistic for the current LWP. */ void diff --git a/usr/src/uts/common/os/main.c b/usr/src/uts/common/os/main.c index 7c5cd30915..03ada0c1e4 100644 --- a/usr/src/uts/common/os/main.c +++ b/usr/src/uts/common/os/main.c @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -95,7 +96,7 @@ kmem_cache_t *process_cache; /* kmem cache for proc structures */ * Process 0's lwp directory and lwpid hash table. */ lwpdir_t p0_lwpdir[2]; -lwpdir_t *p0_tidhash[2]; +tidhash_t p0_tidhash[2]; lwpent_t p0_lep; /* @@ -526,7 +527,7 @@ main(void) p0_lep.le_thread = curthread; p0_lep.le_lwpid = curthread->t_tid; p0_lep.le_start = curthread->t_start; - lwp_hash_in(p, &p0_lep); + lwp_hash_in(p, &p0_lep, p0_tidhash, 2, 0); /* * Initialize extended accounting. diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h index a8a8606245..43407bab38 100644 --- a/usr/src/uts/common/sys/proc.h +++ b/usr/src/uts/common/sys/proc.h @@ -31,7 +31,6 @@ #define _SYS_PROC_H #include <sys/time.h> - #include <sys/thread.h> #include <sys/cred.h> #include <sys/user.h> @@ -65,9 +64,6 @@ struct prof { long pr_samples; /* sample count */ }; -/* hash function for the lwpid hash table, p->p_tidhash[] */ -#define TIDHASH(p, tid) ((tid) & ((p)->p_tidhash_sz - 1)) - /* * An lwp directory entry. * If le_thread != NULL, this is an active lwp. @@ -109,6 +105,23 @@ typedef struct lwpdir { struct lwpent *ld_entry; /* lwp directory entry */ } lwpdir_t; +/* + * Element of the p_tidhash thread-id (lwpid) hash table. + */ +typedef struct tidhash { + kmutex_t th_lock; + lwpdir_t *th_list; +} tidhash_t; + +/* + * Retired tidhash hash tables. + */ +typedef struct ret_tidhash { + struct ret_tidhash *rth_next; + tidhash_t *rth_tidhash; + uint_t rth_tidhash_sz; +} ret_tidhash_t; + struct pool; struct task; struct zone; @@ -209,9 +222,10 @@ typedef struct proc { kthread_t *p_tlist; /* circular list of threads */ lwpdir_t *p_lwpdir; /* thread (lwp) directory */ lwpdir_t *p_lwpfree; /* p_lwpdir free list */ - lwpdir_t **p_tidhash; /* tid (lwpid) lookup hash table */ + tidhash_t *p_tidhash; /* tid (lwpid) lookup hash table */ uint_t p_lwpdir_sz; /* number of p_lwpdir[] entries */ uint_t p_tidhash_sz; /* number of p_tidhash[] entries */ + ret_tidhash_t *p_ret_tidhash; /* retired tidhash hash tables */ uint64_t p_lgrpset; /* unprotected hint of set of lgrps */ /* on which process has threads */ volatile lgrp_id_t p_t1_lgrpid; /* main's thread lgroup id */ @@ -714,9 +728,10 @@ extern klwp_t *lwp_create( int cid, id_t lwpid); extern kthread_t *idtot(proc_t *, id_t); -extern void lwp_hash_in(proc_t *, lwpent_t *); +extern void lwp_hash_in(proc_t *, lwpent_t *, tidhash_t *, uint_t, int); extern void lwp_hash_out(proc_t *, id_t); extern lwpdir_t *lwp_hash_lookup(proc_t *, id_t); +extern lwpdir_t *lwp_hash_lookup_and_lock(proc_t *, id_t, kmutex_t **); extern void lwp_create_done(kthread_t *); extern void lwp_exit(void); extern void lwp_pcb_exit(void); diff --git a/usr/src/uts/common/syscall/lwpsys.c b/usr/src/uts/common/syscall/lwpsys.c index 5e1f378125..40f242c7b4 100644 --- a/usr/src/uts/common/syscall/lwpsys.c +++ b/usr/src/uts/common/syscall/lwpsys.c @@ -18,15 +18,14 @@ * * CDDL HEADER END */ + /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/param.h> #include <sys/types.h> #include <sys/sysmacros.h> @@ -54,6 +53,27 @@ idtot(proc_t *p, id_t lwpid) } /* + * Same as idtot(), but acquire and return + * the tid hash table entry lock on success. + * This allows lwp_unpark() to do its job without acquiring + * p->p_lock (and thereby causing congestion problems when + * the application calls lwp_unpark() too often). + */ +static kthread_t * +idtot_and_lock(proc_t *p, id_t lwpid, kmutex_t **mpp) +{ + lwpdir_t *ldp; + kthread_t *t; + + if ((ldp = lwp_hash_lookup_and_lock(p, lwpid, mpp)) != NULL) { + if ((t = ldp->ld_entry->le_thread) == NULL) + mutex_exit(*mpp); + return (t); + } + return (NULL); +} + +/* * Stop an lwp of the current process */ int @@ -373,18 +393,18 @@ lwp_unpark(id_t lwpid) { proc_t *p = ttoproc(curthread); kthread_t *t; + kmutex_t *mp; int error = 0; - mutex_enter(&p->p_lock); - if ((t = idtot(p, lwpid)) == NULL) + if ((t = idtot_and_lock(p, lwpid, &mp)) == NULL) { error = ESRCH; - else { + } else { mutex_enter(&t->t_delay_lock); t->t_unpark = 1; cv_signal(&t->t_delay_cv); mutex_exit(&t->t_delay_lock); + mutex_exit(mp); } - mutex_exit(&p->p_lock); return (error); } @@ -405,17 +425,17 @@ lwp_unpark_cancel(id_t lwpid) { proc_t *p = ttoproc(curthread); kthread_t *t; + kmutex_t *mp; int error = 0; - mutex_enter(&p->p_lock); - if ((t = idtot(p, lwpid)) == NULL) { + if ((t = idtot_and_lock(p, lwpid, &mp)) == NULL) { error = ESRCH; } else { mutex_enter(&t->t_delay_lock); t->t_unpark = 0; mutex_exit(&t->t_delay_lock); + mutex_exit(mp); } - mutex_exit(&p->p_lock); return (error); } @@ -528,6 +548,7 @@ lwp_unpark_all(id_t *lwpidp, int nids) { proc_t *p = ttoproc(curthread); kthread_t *t; + kmutex_t *mp; int error = 0; id_t *lwpid; size_t lwpidsz; @@ -545,18 +566,17 @@ lwp_unpark_all(id_t *lwpidp, int nids) error = EFAULT; break; } - mutex_enter(&p->p_lock); for (i = 0; i < n; i++) { - if ((t = idtot(p, lwpid[i])) == NULL) + if ((t = idtot_and_lock(p, lwpid[i], &mp)) == NULL) { error = ESRCH; - else { + } else { mutex_enter(&t->t_delay_lock); t->t_unpark = 1; cv_signal(&t->t_delay_cv); mutex_exit(&t->t_delay_lock); + mutex_exit(mp); } } - mutex_exit(&p->p_lock); lwpidp += n; nids -= n; } |