struct thread *td = curthread;
struct lwp *lp = td->td_lwp;
struct proc *p = lp->lwp_proc;
+ int dowake = 0;
/*
* lwp_exit() may be called without setting LWP_WEXIT, so
lwp_rb_tree_RB_REMOVE(&p->p_lwp_tree, lp);
--p->p_nthreads;
if (p->p_nthreads <= 1)
- wakeup(&p->p_nthreads);
+ dowake = 1;
lwkt_gettoken(&deadlwp_token);
LIST_INSERT_HEAD(&deadlwp_list[mycpuid], lp, u.lwp_reap_entry);
taskqueue_enqueue(taskqueue_thread[mycpuid],
} else {
--p->p_nthreads;
if (p->p_nthreads <= 1)
- wakeup(&p->p_nthreads);
+ dowake = 1;
}
/*
- * Release p_token. The mp_token may also be held and we depend on
- * the lwkt_switch() code to clean it up.
+ * Release p_token. Issue the wakeup() on p_nthreads if necessary,
+ * as late as possible to give us a chance to actually deschedule and
+ * switch away before another cpu core hits reaplwp().
*/
lwkt_reltoken(&p->p_token);
+ if (dowake)
+ wakeup(&p->p_nthreads);
cpu_lwp_exit();
}
while (p->p_lock)
tsleep(p, 0, "reap4", hz);
kfree(p, M_PROC);
- nprocs--;
+ atomic_add_int(&nprocs, -1);
error = 0;
goto done;
}
static void
reaplwp(struct lwp *lp)
{
- while (lwp_wait(lp) == 0)
- tsleep(lp, 0, "lwpreap", 1);
+ if (lwp_wait(lp) == 0) {
+ tsleep_interlock(lp, 0);
+ while (lwp_wait(lp) == 0)
+ tsleep(lp, PINTERLOCKED, "lwpreap", 1);
+ }
lwp_dispose(lp);
}
error = EAGAIN;
goto done;
}
+
/*
* Increment the nprocs resource before blocking can occur. There
* are hard-limits as to the number of processes that can run.
*/
- nprocs++;
+ atomic_add_int(&nprocs, 1);
/*
* Increment the count of procs running with this uid. Don't allow
/*
* Back out the process count
*/
- nprocs--;
+ atomic_add_int(&nprocs, -1);
if (ppsratecheck(&lastfail, &curfail, 1))
kprintf("maxproc limit exceeded by uid %d, please "
"see tuning(7) and login.conf(5).\n", uid);
RB_INIT(&p2->p_lwp_tree);
spin_init(&p2->p_spin);
- lwkt_token_init(&p2->p_token, "iproc");
+ lwkt_token_init(&p2->p_token, "proc");
p2->p_lasttid = -1; /* first tid will be 0 */
/*
lwkt_reltoken(&pptr->p_token);
varsymset_init(&p2->p_varsymset, &p1->p_varsymset);
- callout_init(&p2->p_ithandle);
+ callout_init_mp(&p2->p_ithandle);
#ifdef KTRACE
/*