diff --git a/sys/kern/lwkt_thread.c b/sys/kern/lwkt_thread.c
index a3b07be..9a62210 100644
--- a/sys/kern/lwkt_thread.c
+++ b/sys/kern/lwkt_thread.c
@@ -977,28 +977,14 @@ static __inline
 void
 _lwkt_schedule_post(globaldata_t gd, thread_t ntd, int cpri, int reschedok)
 {
-    int mypri;
+    thread_t otd;
 
     if (ntd->td_flags & TDF_RUNQ) {
 	if (ntd->td_preemptable && reschedok) {
 	    ntd->td_preemptable(ntd, cpri);	/* YYY +token */
 	} else if (reschedok) {
-	    /*
-	     * This is a little sticky.  Due to the passive release function
-	     * the LWKT priority can wiggle around for threads acting in
-	     * the kernel on behalf of a user process.  We do not want this
-	     * to effect the comparison per-say.
-	     *
-	     * What will happen is that the current user process will be
-	     * allowed to run until the next hardclock at which time a
-	     * forced need_lwkt_resched() will allow the other kernel mode
-	     * threads to get in their two cents.  This prevents cavitation.
-	     */
-	    mypri = gd->gd_curthread->td_pri & TDPRI_MASK;
-	    if (mypri >= TDPRI_USER_IDLE && mypri <= TDPRI_USER_REAL)
-		mypri = TDPRI_KERN_USER;
-
-	    if ((ntd->td_pri & TDPRI_MASK) > mypri)
+	    otd = curthread;
+	    if ((ntd->td_pri & TDPRI_MASK) > (otd->td_pri & TDPRI_MASK))
 		need_lwkt_resched();
 	}
     }
@@ -1179,6 +1165,22 @@ lwkt_setpri_self(int pri)
 }
 
 /*
+ * Return non-zero if runnable threads exist with a higher priority
+ * then the thread argument.  Typically called after the caller has
+ * lowered his priority to check whether the lowered priority requires
+ * switching away to higher priority threads.
+ */
+int
+lwkt_check_resched(thread_t td)
+{
+	globaldata_t gd = mycpu;
+	
+	if (gd->gd_runqmask > (2 << (td->td_pri & TDPRI_MASK)) - 1)
+		return(1);
+	return(0);
+}
+
+/*
  * Migrate the current thread to the specified cpu. 
  *
  * This is accomplished by descheduling ourselves from the current cpu,
diff --git a/sys/kern/usched_bsd4.c b/sys/kern/usched_bsd4.c
index c986e17..727e3b1 100644
--- a/sys/kern/usched_bsd4.c
+++ b/sys/kern/usched_bsd4.c
@@ -231,6 +231,7 @@ bsd4_acquire_curproc(struct lwp *lp)
 	globaldata_t gd = mycpu;
 	bsd4_pcpu_t dd = &bsd4_pcpu[gd->gd_cpuid];
 
+	KKASSERT(0);
 	/*
 	 * Possibly select another thread, or keep the current thread.
 	 */
@@ -319,6 +320,7 @@ bsd4_release_curproc(struct lwp *lp)
 		 */
 		KKASSERT((lp->lwp_flag & LWP_ONRUNQ) == 0);
 		dd->uschedcp = NULL;	/* don't let lp be selected */
+		dd->upri = PRIBASE_NULL;
 		bsd4_select_curproc(gd);
 	}
 }
@@ -503,23 +505,20 @@ bsd4_setrunqueue(struct lwp *lp)
 	 * If the LWP has higher priority (lower lwp_priority value) on
 	 * its target cpu, reschedule on that cpu.
 	 */
-	{
-		if ((dd->upri & ~PPQMASK) > (lp->lwp_priority & ~PPQMASK)) {
-			dd->upri = lp->lwp_priority;
-			spin_unlock_wr(&bsd4_spin);
+	if ((dd->upri & ~PPQMASK) > (lp->lwp_priority & ~PPQMASK)) {
+		dd->upri = lp->lwp_priority;
+		spin_unlock_wr(&bsd4_spin);
 #ifdef SMP
-			if (gd == mycpu) {
-				need_user_resched();
-			} else {
-				lwkt_send_ipiq(gd, need_user_resched_remote,
-					       NULL);
-			}
-#else
+		if (gd == mycpu) {
 			need_user_resched();
-#endif
-			crit_exit();
-			return;
+		} else {
+			lwkt_send_ipiq(gd, need_user_resched_remote, NULL);
 		}
+#else
+		need_user_resched();
+#endif
+		crit_exit();
+		return;
 	}
 	spin_unlock_wr(&bsd4_spin);
 
@@ -536,7 +535,7 @@ bsd4_setrunqueue(struct lwp *lp)
 	 * XXX P_PASSIVE_ACQ
 	 */
 	mask = ~bsd4_curprocmask & bsd4_rdyprocmask & mycpu->gd_other_cpus &
-	    lp->lwp_cpumask;
+		lp->lwp_cpumask;
 	if (mask) {
 		cpuid = bsd4_scancpu;
 		if (++cpuid == ncpus)
@@ -796,7 +795,7 @@ bsd4_resetpriority(struct lwp *lp)
 	 */
 	if (reschedcpu >= 0) {
 		dd = &bsd4_pcpu[reschedcpu];
-		if ((dd->upri & ~PRIMASK) > (lp->lwp_priority & ~PRIMASK)) {
+		if ((dd->upri & ~PPQMASK) > (lp->lwp_priority & ~PPQMASK)) {
 			dd->upri = lp->lwp_priority;
 #ifdef SMP
 			if (reschedcpu == mycpu->gd_cpuid) {
diff --git a/sys/platform/pc32/i386/trap.c b/sys/platform/pc32/i386/trap.c
index c13a077..20c87f9 100644
--- a/sys/platform/pc32/i386/trap.c
+++ b/sys/platform/pc32/i386/trap.c
@@ -323,63 +323,59 @@ static __inline void
 userexit(struct lwp *lp)
 {
 	struct thread *td = lp->lwp_thread;
-	globaldata_t gd = td->td_gd;
 
-#if 0
 	/*
-	 * If a user reschedule is requested force a new process to be
-	 * chosen by releasing the current process.  Our process will only
-	 * be chosen again if it has a considerably better priority.
+	 * Shortcut - we did not release, no other LWKT threads have a
+	 * higher priority, no user reschedule is pending, and we aren't
+	 * stopped.
+	 *
+	 * We retain the current process designation and can simply return.
 	 */
-	if (user_resched_wanted())
-		lp->lwp_proc->p_usched->release_curproc(lp);
-#endif
+	if (td->td_release && lwkt_check_resched(td) == 0 &&
+	    !user_resched_wanted() && lp->lwp_proc->p_stat != SSTOP) {
+		return;
+	}
 
+again:
 	/*
-	 * Handle a LWKT reschedule request first.  Since our passive release
-	 * is still in place we do not have to do anything special.  This
-	 * will also allow other kernel threads running on behalf of user
-	 * mode to force us to release and acquire the current process before
-	 * we do.
+	 * If a stop is requested do it now, without waiting for the
+	 * current process designation.
 	 */
-	while (lwkt_resched_wanted()) {
-		lwkt_switch();
+	while (lp->lwp_proc->p_stat == SSTOP) {
+		get_mplock();
+		tstop();
+		rel_mplock();
+	}
 
-		/*
-		 * The thread that preempted us may have stopped our process.
-		 */
-		while (lp->lwp_proc->p_stat == SSTOP) {
-			get_mplock();
-			tstop();
-			rel_mplock();
-		}
+	/*
+	 * We need to get into a released state and restore the user
+	 * lwkt priority.
+	 */
+	if (td->td_release) {
+		td->td_release = NULL;
+		lp->lwp_proc->p_usched->release_curproc(lp);
+	} else {
+		lwkt_setpri_self(TDPRI_USER_NORM);
 	}
 
 	/*
-	 * Acquire the current process designation for this user scheduler
-	 * on this cpu.  This will also handle any user-reschedule requests.
+	 * Now we deschedule and add ourselves to the user scheduler
+	 * run queue, then switch away until we become the current process.
 	 *
-	 * If we never blocked we never released and this function is
-	 * typically a nop.  However, if a user reschedule was requested
-	 * this function may allow another user process to run before
-	 * returning.
+	 * When we are switched back in we will be the current process again.
 	 */
-	lp->lwp_proc->p_usched->acquire_curproc(lp);
-	/* We may have switched cpus on acquisition */
-	gd = td->td_gd;
+	lwkt_deschedule_self(td);
+	lp->lwp_proc->p_usched->setrunqueue(lp);
+	lwkt_switch();
 
 	/*
-	 * Reduce our priority in preparation for a return to userland.  If
-	 * our passive release function was still in place, our priority was
-	 * never raised and does not need to be reduced.
-	 *
-	 * Note that at this point there may be other LWKT thread at
-	 * TDPRI_KERN_USER (aka higher then our current priority).  We
-	 * do NOT want to run these threads yet.
+	 * A stop request may have occured while we were blocked.
+	 * Another user reschedule may have occured while we were blocked.
 	 */
-	if (td->td_release == NULL)
-		lwkt_setpri_self(TDPRI_USER_NORM);
-	td->td_release = NULL;
+	if (lp->lwp_proc->p_stat == SSTOP || user_resched_wanted()) {
+		td->td_release = passive_release;
+		goto again;
+	}
 }
 
 #if !defined(KTR_KERNENTRY)
diff --git a/sys/sys/thread.h b/sys/sys/thread.h
index 1a540d2..393b3b0 100644
--- a/sys/sys/thread.h
+++ b/sys/sys/thread.h
@@ -360,6 +360,7 @@ extern lwkt_token_t lwkt_token_pool_get(void *);
 
 extern void lwkt_setpri(thread_t, int);
 extern void lwkt_setpri_self(int);
+extern int lwkt_check_resched(thread_t);
 extern void lwkt_setcpu_self(struct globaldata *);
 extern void lwkt_migratecpu(int);
 
