version 1.37, 2008/03/17 16:55:27 |
version 1.37.2.2, 2008/11/01 21:22:27 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by the NetBSD |
|
* Foundation, Inc. and its contributors. |
|
* 4. Neither the name of The NetBSD Foundation nor the names of its |
|
* contributors may be used to endorse or promote products derived |
|
* from this software without specific prior written permission. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
Line 57 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 50 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#include <uvm/uvm_extern.h> |
#include <uvm/uvm_extern.h> |
|
|
|
#include "opt_sa.h" |
|
|
#define LWP_UNPARK_MAX 1024 |
#define LWP_UNPARK_MAX 1024 |
|
|
syncobj_t lwp_park_sobj = { |
syncobj_t lwp_park_sobj = { |
Line 91 sys__lwp_create(struct lwp *l, const str |
|
Line 86 sys__lwp_create(struct lwp *l, const str |
|
ucontext_t *newuc; |
ucontext_t *newuc; |
int error, lid; |
int error, lid; |
|
|
|
#ifdef KERN_SA |
|
mutex_enter(p->p_lock); |
|
if ((p->p_sflag & (PS_SA | PS_WEXIT)) != 0 || p->p_sa != NULL) { |
|
mutex_exit(p->p_lock); |
|
return EINVAL; |
|
} |
|
mutex_exit(p->p_lock); |
|
#endif |
|
|
newuc = pool_get(&lwp_uc_pool, PR_WAITOK); |
newuc = pool_get(&lwp_uc_pool, PR_WAITOK); |
|
|
error = copyin(SCARG(uap, ucp), newuc, p->p_emul->e_ucsize); |
error = copyin(SCARG(uap, ucp), newuc, p->p_emul->e_ucsize); |
Line 128 sys__lwp_create(struct lwp *l, const str |
|
Line 132 sys__lwp_create(struct lwp *l, const str |
|
* it be created in suspended state. If the process is stopping, |
* it be created in suspended state. If the process is stopping, |
* then the LWP is created stopped. |
* then the LWP is created stopped. |
*/ |
*/ |
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
lwp_lock(l2); |
lwp_lock(l2); |
if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0 && |
if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0 && |
(l->l_flag & (LW_WREBOOT | LW_WSUSPEND | LW_WEXIT)) == 0) { |
(l->l_flag & (LW_WREBOOT | LW_WSUSPEND | LW_WEXIT)) == 0) { |
Line 145 sys__lwp_create(struct lwp *l, const str |
|
Line 149 sys__lwp_create(struct lwp *l, const str |
|
l2->l_stat = LSSUSPENDED; |
l2->l_stat = LSSUSPENDED; |
lwp_unlock_to(l2, l2->l_cpu->ci_schedstate.spc_lwplock); |
lwp_unlock_to(l2, l2->l_cpu->ci_schedstate.spc_lwplock); |
} |
} |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
return 0; |
return 0; |
} |
} |
Line 195 sys__lwp_suspend(struct lwp *l, const st |
|
Line 199 sys__lwp_suspend(struct lwp *l, const st |
|
struct lwp *t; |
struct lwp *t; |
int error; |
int error; |
|
|
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
|
|
|
#ifdef KERN_SA |
|
if ((p->p_sflag & PS_SA) != 0 || p->p_sa != NULL) { |
|
mutex_exit(p->p_lock); |
|
return EINVAL; |
|
} |
|
#endif |
|
|
if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { |
if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return ESRCH; |
return ESRCH; |
} |
} |
|
|
Line 212 sys__lwp_suspend(struct lwp *l, const st |
|
Line 224 sys__lwp_suspend(struct lwp *l, const st |
|
if ((t == l && p->p_nrlwps == 1) || |
if ((t == l && p->p_nrlwps == 1) || |
(l->l_flag & (LW_WCORE | LW_WEXIT)) != 0) { |
(l->l_flag & (LW_WCORE | LW_WEXIT)) != 0) { |
lwp_unlock(t); |
lwp_unlock(t); |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return EDEADLK; |
return EDEADLK; |
} |
} |
|
|
Line 224 sys__lwp_suspend(struct lwp *l, const st |
|
Line 236 sys__lwp_suspend(struct lwp *l, const st |
|
*/ |
*/ |
error = lwp_suspend(l, t); |
error = lwp_suspend(l, t); |
if (error) { |
if (error) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return error; |
return error; |
} |
} |
|
|
Line 236 sys__lwp_suspend(struct lwp *l, const st |
|
Line 248 sys__lwp_suspend(struct lwp *l, const st |
|
* o target LWP exited |
* o target LWP exited |
*/ |
*/ |
for (;;) { |
for (;;) { |
error = cv_wait_sig(&p->p_lwpcv, &p->p_smutex); |
error = cv_wait_sig(&p->p_lwpcv, p->p_lock); |
if (error) { |
if (error) { |
error = ERESTART; |
error = ERESTART; |
break; |
break; |
Line 253 sys__lwp_suspend(struct lwp *l, const st |
|
Line 265 sys__lwp_suspend(struct lwp *l, const st |
|
(t->l_flag & LW_WSUSPEND) == 0) |
(t->l_flag & LW_WSUSPEND) == 0) |
break; |
break; |
} |
} |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
return error; |
return error; |
} |
} |
Line 270 sys__lwp_continue(struct lwp *l, const s |
|
Line 282 sys__lwp_continue(struct lwp *l, const s |
|
|
|
error = 0; |
error = 0; |
|
|
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { |
if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return ESRCH; |
return ESRCH; |
} |
} |
|
|
lwp_lock(t); |
lwp_lock(t); |
lwp_continue(t); |
lwp_continue(t); |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
return error; |
return error; |
} |
} |
Line 294 sys__lwp_wakeup(struct lwp *l, const str |
|
Line 306 sys__lwp_wakeup(struct lwp *l, const str |
|
int error; |
int error; |
|
|
p = l->l_proc; |
p = l->l_proc; |
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
|
|
if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { |
if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return ESRCH; |
return ESRCH; |
} |
} |
|
|
Line 316 sys__lwp_wakeup(struct lwp *l, const str |
|
Line 328 sys__lwp_wakeup(struct lwp *l, const str |
|
error = 0; |
error = 0; |
} |
} |
|
|
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
return error; |
return error; |
} |
} |
Line 332 sys__lwp_wait(struct lwp *l, const struc |
|
Line 344 sys__lwp_wait(struct lwp *l, const struc |
|
int error; |
int error; |
lwpid_t dep; |
lwpid_t dep; |
|
|
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
error = lwp_wait1(l, SCARG(uap, wait_for), &dep, 0); |
error = lwp_wait1(l, SCARG(uap, wait_for), &dep, 0); |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
if (error) |
if (error) |
return error; |
return error; |
Line 367 sys__lwp_kill(struct lwp *l, const struc |
|
Line 379 sys__lwp_kill(struct lwp *l, const struc |
|
|
|
KSI_INIT(&ksi); |
KSI_INIT(&ksi); |
ksi.ksi_signo = signo; |
ksi.ksi_signo = signo; |
ksi.ksi_code = SI_USER; |
ksi.ksi_code = SI_LWP; |
ksi.ksi_pid = p->p_pid; |
ksi.ksi_pid = p->p_pid; |
ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); |
ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); |
ksi.ksi_lid = SCARG(uap, target); |
ksi.ksi_lid = SCARG(uap, target); |
|
|
mutex_enter(&proclist_mutex); |
mutex_enter(proc_lock); |
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) |
if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) |
error = ESRCH; |
error = ESRCH; |
else if (signo != 0) |
else if (signo != 0) |
kpsignal2(p, &ksi); |
kpsignal2(p, &ksi); |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
mutex_exit(&proclist_mutex); |
mutex_exit(proc_lock); |
|
|
return error; |
return error; |
} |
} |
Line 398 sys__lwp_detach(struct lwp *l, const str |
|
Line 410 sys__lwp_detach(struct lwp *l, const str |
|
target = SCARG(uap, target); |
target = SCARG(uap, target); |
p = l->l_proc; |
p = l->l_proc; |
|
|
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
|
|
if (l->l_lid == target) |
if (l->l_lid == target) |
t = l; |
t = l; |
Line 442 sys__lwp_detach(struct lwp *l, const str |
|
Line 454 sys__lwp_detach(struct lwp *l, const str |
|
} else |
} else |
error = ESRCH; |
error = ESRCH; |
|
|
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
return error; |
return error; |
} |
} |
Line 460 lwp_unpark(lwpid_t target, const void *h |
|
Line 472 lwp_unpark(lwpid_t target, const void *h |
|
sleepq_t *sq; |
sleepq_t *sq; |
wchan_t wchan; |
wchan_t wchan; |
int swapin; |
int swapin; |
|
kmutex_t *mp; |
proc_t *p; |
proc_t *p; |
lwp_t *t; |
lwp_t *t; |
|
|
Line 469 lwp_unpark(lwpid_t target, const void *h |
|
Line 482 lwp_unpark(lwpid_t target, const void *h |
|
*/ |
*/ |
p = curproc; |
p = curproc; |
wchan = lwp_park_wchan(p, hint); |
wchan = lwp_park_wchan(p, hint); |
sq = sleeptab_lookup(&lwp_park_tab, wchan); |
sq = sleeptab_lookup(&lwp_park_tab, wchan, &mp); |
|
|
TAILQ_FOREACH(t, &sq->sq_queue, l_sleepchain) |
TAILQ_FOREACH(t, sq, l_sleepchain) |
if (t->l_proc == p && t->l_lid == target) |
if (t->l_proc == p && t->l_lid == target) |
break; |
break; |
|
|
if (__predict_true(t != NULL)) { |
if (__predict_true(t != NULL)) { |
swapin = sleepq_remove(sq, t); |
swapin = sleepq_remove(sq, t); |
sleepq_unlock(sq); |
mutex_spin_exit(mp); |
if (swapin) |
if (swapin) |
uvm_kick_scheduler(); |
uvm_kick_scheduler(); |
return 0; |
return 0; |
Line 487 lwp_unpark(lwpid_t target, const void *h |
|
Line 500 lwp_unpark(lwpid_t target, const void *h |
|
* The LWP hasn't parked yet. Take the hit and mark the |
* The LWP hasn't parked yet. Take the hit and mark the |
* operation as pending. |
* operation as pending. |
*/ |
*/ |
sleepq_unlock(sq); |
mutex_spin_exit(mp); |
|
|
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
if ((t = lwp_find(p, target)) == NULL) { |
if ((t = lwp_find(p, target)) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return ESRCH; |
return ESRCH; |
} |
} |
|
|
Line 512 lwp_unpark(lwpid_t target, const void *h |
|
Line 525 lwp_unpark(lwpid_t target, const void *h |
|
lwp_unlock(t); |
lwp_unlock(t); |
} |
} |
|
|
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return 0; |
return 0; |
} |
} |
|
|
Line 521 lwp_park(struct timespec *ts, const void |
|
Line 534 lwp_park(struct timespec *ts, const void |
|
{ |
{ |
struct timespec tsx; |
struct timespec tsx; |
sleepq_t *sq; |
sleepq_t *sq; |
|
kmutex_t *mp; |
wchan_t wchan; |
wchan_t wchan; |
int timo, error; |
int timo, error; |
lwp_t *l; |
lwp_t *l; |
Line 541 lwp_park(struct timespec *ts, const void |
|
Line 555 lwp_park(struct timespec *ts, const void |
|
/* Find and lock the sleep queue. */ |
/* Find and lock the sleep queue. */ |
l = curlwp; |
l = curlwp; |
wchan = lwp_park_wchan(l->l_proc, hint); |
wchan = lwp_park_wchan(l->l_proc, hint); |
sq = sleeptab_lookup(&lwp_park_tab, wchan); |
sq = sleeptab_lookup(&lwp_park_tab, wchan, &mp); |
|
|
/* |
/* |
* Before going the full route and blocking, check to see if an |
* Before going the full route and blocking, check to see if an |
Line 551 lwp_park(struct timespec *ts, const void |
|
Line 565 lwp_park(struct timespec *ts, const void |
|
if ((l->l_flag & (LW_CANCELLED | LW_UNPARKED)) != 0) { |
if ((l->l_flag & (LW_CANCELLED | LW_UNPARKED)) != 0) { |
l->l_flag &= ~(LW_CANCELLED | LW_UNPARKED); |
l->l_flag &= ~(LW_CANCELLED | LW_UNPARKED); |
lwp_unlock(l); |
lwp_unlock(l); |
sleepq_unlock(sq); |
mutex_spin_exit(mp); |
return EALREADY; |
return EALREADY; |
} |
} |
lwp_unlock_to(l, sq->sq_mutex); |
lwp_unlock_to(l, mp); |
l->l_biglocks = 0; |
l->l_biglocks = 0; |
sleepq_enqueue(sq, wchan, "parked", &lwp_park_sobj); |
sleepq_enqueue(sq, wchan, "parked", &lwp_park_sobj); |
error = sleepq_block(timo, true); |
error = sleepq_block(timo, true); |
Line 578 lwp_park(struct timespec *ts, const void |
|
Line 592 lwp_park(struct timespec *ts, const void |
|
* requests that it be unparked. |
* requests that it be unparked. |
*/ |
*/ |
int |
int |
sys__lwp_park(struct lwp *l, const struct sys__lwp_park_args *uap, register_t *retval) |
sys____lwp_park50(struct lwp *l, const struct sys____lwp_park50_args *uap, |
|
register_t *retval) |
{ |
{ |
/* { |
/* { |
syscallarg(const struct timespec *) ts; |
syscallarg(const struct timespec *) ts; |
Line 632 sys__lwp_unpark_all(struct lwp *l, const |
|
Line 647 sys__lwp_unpark_all(struct lwp *l, const |
|
wchan_t wchan; |
wchan_t wchan; |
lwpid_t targets[32], *tp, *tpp, *tmax, target; |
lwpid_t targets[32], *tp, *tpp, *tmax, target; |
int swapin, error; |
int swapin, error; |
|
kmutex_t *mp; |
u_int ntargets; |
u_int ntargets; |
size_t sz; |
size_t sz; |
|
|
Line 671 sys__lwp_unpark_all(struct lwp *l, const |
|
Line 687 sys__lwp_unpark_all(struct lwp *l, const |
|
|
|
swapin = 0; |
swapin = 0; |
wchan = lwp_park_wchan(p, SCARG(uap, hint)); |
wchan = lwp_park_wchan(p, SCARG(uap, hint)); |
sq = sleeptab_lookup(&lwp_park_tab, wchan); |
sq = sleeptab_lookup(&lwp_park_tab, wchan, &mp); |
|
|
for (tmax = tp + ntargets, tpp = tp; tpp < tmax; tpp++) { |
for (tmax = tp + ntargets, tpp = tp; tpp < tmax; tpp++) { |
target = *tpp; |
target = *tpp; |
Line 680 sys__lwp_unpark_all(struct lwp *l, const |
|
Line 696 sys__lwp_unpark_all(struct lwp *l, const |
|
* Easy case: search for the LWP on the sleep queue. If |
* Easy case: search for the LWP on the sleep queue. If |
* it's parked, remove it from the queue and set running. |
* it's parked, remove it from the queue and set running. |
*/ |
*/ |
TAILQ_FOREACH(t, &sq->sq_queue, l_sleepchain) |
TAILQ_FOREACH(t, sq, l_sleepchain) |
if (t->l_proc == p && t->l_lid == target) |
if (t->l_proc == p && t->l_lid == target) |
break; |
break; |
|
|
Line 693 sys__lwp_unpark_all(struct lwp *l, const |
|
Line 709 sys__lwp_unpark_all(struct lwp *l, const |
|
* The LWP hasn't parked yet. Take the hit and |
* The LWP hasn't parked yet. Take the hit and |
* mark the operation as pending. |
* mark the operation as pending. |
*/ |
*/ |
sleepq_unlock(sq); |
mutex_spin_exit(mp); |
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
if ((t = lwp_find(p, target)) == NULL) { |
if ((t = lwp_find(p, target)) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
sleepq_lock(sq); |
mutex_spin_enter(mp); |
continue; |
continue; |
} |
} |
lwp_lock(t); |
lwp_lock(t); |
Line 718 sys__lwp_unpark_all(struct lwp *l, const |
|
Line 734 sys__lwp_unpark_all(struct lwp *l, const |
|
lwp_unlock(t); |
lwp_unlock(t); |
} |
} |
|
|
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
sleepq_lock(sq); |
mutex_spin_enter(mp); |
} |
} |
|
|
sleepq_unlock(sq); |
mutex_spin_exit(mp); |
if (tp != targets) |
if (tp != targets) |
kmem_free(tp, sz); |
kmem_free(tp, sz); |
if (swapin) |
if (swapin) |
Line 762 sys__lwp_setname(struct lwp *l, const st |
|
Line 778 sys__lwp_setname(struct lwp *l, const st |
|
} |
} |
|
|
p = curproc; |
p = curproc; |
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
if ((t = lwp_find(p, target)) == NULL) { |
if ((t = lwp_find(p, target)) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
kmem_free(name, MAXCOMLEN); |
kmem_free(name, MAXCOMLEN); |
return ESRCH; |
return ESRCH; |
} |
} |
Line 772 sys__lwp_setname(struct lwp *l, const st |
|
Line 788 sys__lwp_setname(struct lwp *l, const st |
|
oname = t->l_name; |
oname = t->l_name; |
t->l_name = name; |
t->l_name = name; |
lwp_unlock(t); |
lwp_unlock(t); |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
if (oname != NULL) |
if (oname != NULL) |
kmem_free(oname, MAXCOMLEN); |
kmem_free(oname, MAXCOMLEN); |
Line 797 sys__lwp_getname(struct lwp *l, const st |
|
Line 813 sys__lwp_getname(struct lwp *l, const st |
|
target = l->l_lid; |
target = l->l_lid; |
|
|
p = curproc; |
p = curproc; |
mutex_enter(&p->p_smutex); |
mutex_enter(p->p_lock); |
if ((t = lwp_find(p, target)) == NULL) { |
if ((t = lwp_find(p, target)) == NULL) { |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
return ESRCH; |
return ESRCH; |
} |
} |
lwp_lock(t); |
lwp_lock(t); |
Line 808 sys__lwp_getname(struct lwp *l, const st |
|
Line 824 sys__lwp_getname(struct lwp *l, const st |
|
else |
else |
strcpy(name, t->l_name); |
strcpy(name, t->l_name); |
lwp_unlock(t); |
lwp_unlock(t); |
mutex_exit(&p->p_smutex); |
mutex_exit(p->p_lock); |
|
|
return copyoutstr(name, SCARG(uap, name), SCARG(uap, len), NULL); |
return copyoutstr(name, SCARG(uap, name), SCARG(uap, len), NULL); |
} |
} |