Tweak change to move SA support from userret() to lwp_userret().
1) Since we want to check for upcalls only once, take LW_SA_UPCALL out of the while(l->l_flags & LW_USERRET) loop. 2) since the goal is to keep SA code out of userret() (and especially all the emulations that include userret() but will never do SA), ALWAYS set LW_SA_UPCALL when we set SAVP_FLAG_NOUPCALLS. Drop the test for it in lwp_userret() since it will never be set bare. 3) Adapt sa_upcall_userret() to clear LW_SA_UPCALL if it's no longer needed. If we have gained upcalls since sa_yield(), we will deliver them next time around. Tested by skrll at.
This commit is contained in:
parent
836c38aba9
commit
04ca26c586
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: compat_sa.c,v 1.5 2008/10/27 16:52:04 wrstuden Exp $ */
|
||||
/* $NetBSD: compat_sa.c,v 1.6 2008/10/28 22:11:36 wrstuden Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2004, 2005, 2006 The NetBSD Foundation, Inc.
|
||||
@ -41,7 +41,7 @@
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_sa.h"
|
||||
__KERNEL_RCSID(0, "$NetBSD: compat_sa.c,v 1.5 2008/10/27 16:52:04 wrstuden Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: compat_sa.c,v 1.6 2008/10/28 22:11:36 wrstuden Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -1117,6 +1117,13 @@ sa_yield(struct lwp *l)
|
||||
* upcalls.
|
||||
*/
|
||||
vp->savp_pflags |= SAVP_FLAG_NOUPCALLS;
|
||||
/*
|
||||
* Now force us to call into sa_upcall_userret()
|
||||
* which will clear SAVP_FLAG_NOUPCALLS
|
||||
*/
|
||||
lwp_lock(l);
|
||||
l->l_flag |= LW_SA_UPCALL;
|
||||
lwp_unlock(l);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1997,11 +2004,25 @@ sa_upcall_userret(struct lwp *l)
|
||||
vp = l->l_savp;
|
||||
|
||||
if (vp->savp_pflags & SAVP_FLAG_NOUPCALLS) {
|
||||
int do_clear = 0;
|
||||
/*
|
||||
* We made upcalls in sa_yield() (otherwise we would
|
||||
* still be in the loop there!). Don't do it again.
|
||||
* Clear LW_SA_UPCALL, unless there are upcalls to deliver.
|
||||
* they will get delivered next time we return to user mode.
|
||||
*/
|
||||
vp->savp_pflags &= ~SAVP_FLAG_NOUPCALLS;
|
||||
mutex_enter(&vp->savp_mutex);
|
||||
if ((vp->savp_woken_count == 0)
|
||||
&& SIMPLEQ_EMPTY(&vp->savp_upcalls)) {
|
||||
do_clear = 1;
|
||||
}
|
||||
mutex_exit(&vp->savp_mutex);
|
||||
if (do_clear) {
|
||||
lwp_lock(l);
|
||||
l->l_flag &= ~LW_SA_UPCALL;
|
||||
lwp_unlock(l);
|
||||
}
|
||||
DPRINTFN(7,("sa_upcall_userret(%d.%d %x) skipping processing\n",
|
||||
p->p_pid, l->l_lid, l->l_flag));
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: kern_lwp.c,v 1.125 2008/10/21 11:51:23 ad Exp $ */
|
||||
/* $NetBSD: kern_lwp.c,v 1.126 2008/10/28 22:11:36 wrstuden Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
@ -206,7 +206,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.125 2008/10/21 11:51:23 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.126 2008/10/28 22:11:36 wrstuden Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_lockdebug.h"
|
||||
@ -1251,8 +1251,11 @@ lwp_userret(struct lwp *l)
|
||||
/*
|
||||
* It should be safe to do this read unlocked on a multiprocessor
|
||||
* system..
|
||||
*
|
||||
* LW_SA_UPCALL will be handled after the while() loop, so don't
|
||||
* consider it now.
|
||||
*/
|
||||
while ((l->l_flag & LW_USERRET) != 0) {
|
||||
while ((l->l_flag & (LW_USERRET & ~(LW_SA_UPCALL))) != 0) {
|
||||
/*
|
||||
* Process pending signals first, unless the process
|
||||
* is dumping core or exiting, where we will instead
|
||||
@ -1317,9 +1320,6 @@ lwp_userret(struct lwp *l)
|
||||
timerupcall(l);
|
||||
if (l->l_flag & LW_SA_UPCALL)
|
||||
sa_upcall_userret(l);
|
||||
else if (__predict_false((l->l_savp)
|
||||
&& (l->l_savp->savp_pflags & SAVP_FLAG_NOUPCALLS)))
|
||||
l->l_savp->savp_pflags &= ~SAVP_FLAG_NOUPCALLS;
|
||||
#endif /* KERN_SA */
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user