diff --git a/sys/kern/sys_lwp.c b/sys/kern/sys_lwp.c index 5464cb8aa5fd..f43c2294d43e 100644 --- a/sys/kern/sys_lwp.c +++ b/sys/kern/sys_lwp.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_lwp.c,v 1.7 2007/02/26 09:20:54 yamt Exp $ */ +/* $NetBSD: sys_lwp.c,v 1.8 2007/03/01 14:55:06 ad Exp $ */ /*- * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.7 2007/02/26 09:20:54 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.8 2007/03/01 14:55:06 ad Exp $"); #include #include @@ -73,6 +73,8 @@ struct evcnt lwp_ev_park_early = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "_lwp_park", "unparked early"); struct evcnt lwp_ev_park_raced = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "_lwp_park", "raced"); +struct evcnt lwp_ev_park_slowpath = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, + NULL, "_lwp_park", "slowpath"); struct evcnt lwp_ev_park_miss = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "_lwp_park", "not parked"); struct evcnt lwp_ev_park_bcast = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, @@ -93,6 +95,7 @@ lwp_sys_init(void) sleeptab_init(&lwp_park_tab); #ifdef LWP_COUNTERS evcnt_attach_static(&lwp_ev_park_early); + evcnt_attach_static(&lwp_ev_park_slowpath); evcnt_attach_static(&lwp_ev_park_raced); evcnt_attach_static(&lwp_ev_park_miss); evcnt_attach_static(&lwp_ev_park_bcast); @@ -150,7 +153,7 @@ sys__lwp_create(struct lwp *l, void *v, register_t *retval) if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) l2->l_stat = LSSTOP; else { - LOCK_ASSERT(lwp_locked(l2, &sched_mutex)); + KASSERT(lwp_locked(l2, &sched_mutex)); p->p_nrlwps++; l2->l_stat = LSRUN; setrunqueue(l2); @@ -483,14 +486,15 @@ sys__lwp_park(struct lwp *l, void *v, register_t *retval) * Before going the full route and blocking, check to see if an * unpark op is pending. */ - if ((l->l_flag & LW_CANCELLED) != 0) { - sleepq_lwp_lock(l); - l->l_flag &= ~LW_CANCELLED; - sleepq_lwp_unlock(l); + lwp_lock(l); + if ((l->l_flag & (LW_CANCELLED | LW_UNPARKED)) != 0) { + l->l_flag &= ~(LW_CANCELLED | LW_UNPARKED); + lwp_unlock(l); sleepq_unlock(sq); LWP_COUNT(lwp_ev_park_early, 1); return EALREADY; } + lwp_unlock_to(l, sq->sq_mutex); /* * For now we ignore the ucontext argument. In the future, we may @@ -498,7 +502,7 @@ sys__lwp_park(struct lwp *l, void *v, register_t *retval) * function could call sleepq_unblock() on our behalf. */ LWP_COUNT(lwp_ev_park, 1); - sleepq_enter(sq, l); + l->l_biglocks = 0; /* For sleepq_unblock() */ sleepq_block(sq, sched_kpri(l), wchan, "parked", timo, 1, &lwp_park_sobj); error = sleepq_unblock(timo, 1); @@ -538,6 +542,7 @@ sys__lwp_unpark(struct lwp *l, void *v, register_t *retval) * The LWP hasn't parked yet. Take the hit * and mark the operation as pending. */ + LWP_COUNT(lwp_ev_park_slowpath, 1); sleepq_unlock(sq); mutex_enter(&p->p_smutex); if ((t = lwp_find(p, target)) == NULL) { @@ -553,7 +558,7 @@ sys__lwp_unpark(struct lwp *l, void *v, register_t *retval) * Wake it in the usual way. */ KASSERT(t->l_syncobj == &lwp_park_sobj); - LOCK_ASSERT(lwp_locked(t, sq->sq_mutex)); + KASSERT(lwp_locked(t, sq->sq_mutex)); LWP_COUNT(lwp_ev_park_raced, 1); } else { /* @@ -561,17 +566,17 @@ sys__lwp_unpark(struct lwp *l, void *v, register_t *retval) * on a different user sync object. The * latter is an application error. */ - t->l_flag |= LW_CANCELLED; + t->l_flag |= LW_UNPARKED; lwp_unlock(t); return 0; } } swapin = sleepq_remove(sq, t); + LWP_COUNT(lwp_ev_park_targ, 1); sleepq_unlock(sq); if (swapin) uvm_kick_scheduler(); - LWP_COUNT(lwp_ev_park_targ, 1); return 0; } @@ -656,6 +661,7 @@ sys__lwp_unpark_all(struct lwp *l, void *v, register_t *retval) * The LWP hasn't parked yet. Take the hit and * mark the operation as pending. */ + LWP_COUNT(lwp_ev_park_slowpath, 1); sleepq_unlock(sq); mutex_enter(&p->p_smutex); if ((t = lwp_find(p, target)) == NULL) { @@ -672,7 +678,7 @@ sys__lwp_unpark_all(struct lwp *l, void *v, register_t *retval) * Wake it in the usual way. */ KASSERT(t->l_syncobj == &lwp_park_sobj); - LOCK_ASSERT(lwp_locked(t, sq->sq_mutex)); + KASSERT(lwp_locked(t, sq->sq_mutex)); LWP_COUNT(lwp_ev_park_raced, 1); swapin |= sleepq_remove(sq, t); unparked++; @@ -682,7 +688,7 @@ sys__lwp_unpark_all(struct lwp *l, void *v, register_t *retval) * on a different user sync object. The * latter is an application error. */ - t->l_flag |= LW_CANCELLED; + t->l_flag |= LW_UNPARKED; lwp_unlock(t); sleepq_lock(sq); } diff --git a/sys/sys/lwp.h b/sys/sys/lwp.h index 6e509df4540b..f589bb0daea9 100644 --- a/sys/sys/lwp.h +++ b/sys/sys/lwp.h @@ -1,4 +1,4 @@ -/* $NetBSD: lwp.h,v 1.54 2007/02/27 15:07:28 yamt Exp $ */ +/* $NetBSD: lwp.h,v 1.55 2007/03/01 14:55:06 ad Exp $ */ /*- * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. @@ -174,6 +174,7 @@ extern struct lwp lwp0; /* LWP for proc0 */ #define LW_PENDSIG 0x01000000 /* Pending signal for us */ #define LW_CANCELLED 0x02000000 /* tsleep should not sleep */ #define LW_WUSERRET 0x04000000 /* Call proc::p_userret on return to user */ +#define LW_UNPARKED 0x01000000 /* unpark op pending */ #define LW_WREBOOT 0x08000000 /* System is rebooting, please suspend */ /* The second set of flags is kept in l_pflag. */