-/* $OpenBSD: kern_synch.c,v 1.193 2023/06/28 08:23:25 claudio Exp $ */
+/* $OpenBSD: kern_synch.c,v 1.194 2023/07/11 07:02:43 claudio Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*
sleep_setup(&sls, ident, priority, wmesg);
- /* XXX - We need to make sure that the mutex doesn't
- * unblock splsched. This can be made a bit more
- * correct when the sched_lock is a mutex.
- */
- spl = MUTEX_OLDIPL(mtx);
- MUTEX_OLDIPL(mtx) = splsched();
mtx_leave(mtx);
/* signal may stop the process, release mutex before that */
error = sleep_finish(&sls, priority, timo, 1);
- if ((priority & PNORELOCK) == 0) {
+ if ((priority & PNORELOCK) == 0)
mtx_enter(mtx);
- MUTEX_OLDIPL(mtx) = spl; /* put the ipl back */
- } else
- splx(spl);
return error;
}
KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0);
KASSERT(ident != &nowake || ISSET(priority, PCATCH) || timo != 0);
+ KASSERT(ident != rwl);
rw_assert_anylock(rwl);
status = rw_status(rwl);
const char *wmesg)
{
struct proc *p = curproc;
+ int s;
#ifdef DIAGNOSTIC
if (p->p_flag & P_CANTSLEEP)
panic("tsleep: not SONPROC");
#endif
- SCHED_LOCK(sls->sls_s);
+ SCHED_LOCK(s);
TRACEPOINT(sched, sleep, NULL);
p->p_wmesg = wmesg;
p->p_slptime = 0;
p->p_slppri = prio & PRIMASK;
+ atomic_setbits_int(&p->p_flag, P_WSLEEP);
TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_runq);
+ if (prio & PCATCH)
+ atomic_setbits_int(&p->p_flag, P_SINTR);
+ p->p_stat = SSLEEP;
+ SCHED_UNLOCK(s);
}
int
sleep_finish(struct sleep_state *sls, int prio, int timo, int do_sleep)
{
struct proc *p = curproc;
- int catch, error = 0, error1 = 0;
+ int s, catch, error = 0, error1 = 0;
catch = prio & PCATCH;
timeout_add(&p->p_sleep_to, timo);
}
+ SCHED_LOCK(s);
if (catch != 0) {
/*
* We put ourselves on the sleep queue and start our
* us to be marked as SSLEEP without resuming us, thus
* we must be ready for sleep when sleep_signal_check() is
* called.
- * If the wakeup happens while we're stopped, p->p_wchan
- * will be NULL upon return from sleep_signal_check(). In
- * that case we need to unwind immediately.
*/
- atomic_setbits_int(&p->p_flag, P_SINTR);
if ((error = sleep_signal_check()) != 0) {
- p->p_stat = SONPROC;
- catch = 0;
- do_sleep = 0;
- } else if (p->p_wchan == NULL) {
catch = 0;
do_sleep = 0;
}
}
+ /*
+ * If the wakeup happens while going to sleep, p->p_wchan
+ * will be NULL. In that case unwind immediately but still
+ * check for possible signals and timeouts.
+ */
+ if (p->p_wchan == NULL)
+ do_sleep = 0;
+
+ atomic_clearbits_int(&p->p_flag, P_WSLEEP);
if (do_sleep) {
- p->p_stat = SSLEEP;
p->p_ru.ru_nvcsw++;
- SCHED_ASSERT_LOCKED();
mi_switch();
} else {
unsleep(p);
+ p->p_stat = SONPROC;
}
#ifdef DIAGNOSTIC
#endif
p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri;
- SCHED_UNLOCK(sls->sls_s);
+ SCHED_UNLOCK(s);
/*
* Even though this belongs to the signal handling part of sleep,
atomic_setbits_int(&p->p_flag, flags);
if (p->p_stat == SSLEEP)
setrunnable(p);
- else
+ else if (p->p_stat == SSTOP)
unsleep(p);
+#ifdef DIAGNOSTIC
+ else
+ panic("wakeup: p_stat is %d", (int)p->p_stat);
+#endif
}
return awakened;
qp = &slpque[LOOKUP(ident)];
for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) {
pnext = TAILQ_NEXT(p, p_runq);
- /*
- * This happens if wakeup(9) is called after enqueuing
- * itself on the sleep queue and both `ident' collide.
- */
- if (p == curproc)
- continue;
#ifdef DIAGNOSTIC
if (p->p_stat != SSLEEP && p->p_stat != SSTOP)
panic("wakeup: p_stat is %d", (int)p->p_stat);
-/* $OpenBSD: proc.h,v 1.344 2023/07/10 03:31:58 guenther Exp $ */
+/* $OpenBSD: proc.h,v 1.345 2023/07/11 07:02:43 claudio Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
#define P_ALRMPEND 0x00000004 /* SIGVTALRM needs to be posted */
#define P_SIGSUSPEND 0x00000008 /* Need to restore before-suspend mask*/
#define P_CANTSLEEP 0x00000010 /* insomniac thread */
+#define P_WSLEEP 0x00000020 /* Working on going to sleep. */
#define P_SINTR 0x00000080 /* Sleep is interruptible. */
#define P_SYSTEM 0x00000200 /* No sigs, stats or swapping. */
#define P_TIMEOUT 0x00000400 /* Timing out during sleep. */
#define P_BITS \
("\20" "\01INKTR" "\02PROFPEND" "\03ALRMPEND" "\04SIGSUSPEND" \
- "\05CANTSLEEP" "\010SINTR" "\012SYSTEM" "\013TIMEOUT" \
+ "\05CANTSLEEP" "\06WSLEEP" "\010SINTR" "\012SYSTEM" "\013TIMEOUT" \
"\016WEXIT" "\020OWEUPC" "\024SUSPSINGLE" "\027XX" \
"\030CONTINUED" "\033THREAD" "\034SUSPSIG" "\035SOFTDEP" "\037CPUPEG")