Skip to content

Commit ed2b086

Browse files
authored
Add a mutex to the sleepq wait interface. (#1378)
1 parent a383782 commit ed2b086

13 files changed

+38
-21
lines changed

include/sys/sleepq.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <sys/types.h>
66
#include <sys/queue.h>
77

8+
typedef struct mtx mtx_t;
89
typedef struct thread thread_t;
910
typedef struct sleepq sleepq_t;
1011

@@ -23,11 +24,14 @@ void sleepq_destroy(sleepq_t *sq);
2324
*
2425
* \param wchan unique sleep queue identifier
2526
* \param waitpt caller associated with sleep action
27+
* \param mtx mutex to release before falling asleep and reacquire
28+
* upon waking up
2629
*/
27-
void sleepq_wait(void *wchan, const void *waitpt);
30+
void sleepq_wait(void *wchan, const void *waitpt, mtx_t *mtx);
2831

2932
/*! \brief Same as \a sleepq_wait but allows the sleep to be interrupted. */
30-
#define sleepq_wait_intr(wchan, waitpt) sleepq_wait_timed((wchan), (waitpt), 0)
33+
#define sleepq_wait_intr(wchan, waitpt, mtx) \
34+
sleepq_wait_timed((wchan), (waitpt), (mtx), 0)
3135

3236
/*! \brief Performs interruptible sleep with timeout.
3337
*
@@ -37,7 +41,8 @@ void sleepq_wait(void *wchan, const void *waitpt);
3741
*
3842
* \param timeout in system ticks, if 0 waits indefinitely
3943
* \returns how the thread was actually woken up */
40-
int sleepq_wait_timed(void *wchan, const void *waitpt, systime_t timeout);
44+
int sleepq_wait_timed(void *wchan, const void *waitpt, mtx_t *mtx,
45+
systime_t timeout);
4146

4247
/*! \brief Wakes up highest priority thread waiting on \a wchan.
4348
*

sys/drv/rtc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static int rtc_time_read(devnode_t *dev, uio_t *uio) {
8080
rtc_state_t *rtc = dev->data;
8181
tm_t t;
8282

83-
sleepq_wait(rtc, NULL);
83+
sleepq_wait(rtc, NULL, NULL);
8484
rtc_gettime(rtc->regs, &t);
8585
int count = snprintf(rtc->asctime, RTC_ASCTIME_SIZE, "%d %d %d %d %d %d",
8686
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour,

sys/kern/callout.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static void callout_thread(void *arg) {
5555

5656
WITH_INTR_DISABLED {
5757
while (TAILQ_EMPTY(&delegated)) {
58-
sleepq_wait(&delegated, NULL);
58+
sleepq_wait(&delegated, NULL, NULL);
5959
}
6060

6161
elem = TAILQ_FIRST(&delegated);
@@ -211,6 +211,6 @@ bool callout_drain(callout_t *handle) {
211211
if (!callout_is_pending(handle) && !callout_is_active(handle))
212212
return false;
213213
while (callout_is_pending(handle) || callout_is_active(handle))
214-
sleepq_wait(handle, NULL);
214+
sleepq_wait(handle, NULL, NULL);
215215
return true;
216216
}

sys/kern/condvar.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void cv_wait(condvar_t *cv, mtx_t *m) {
1515
/* If we got interrupted here and an interrupt filter called
1616
* cv_signal, we would have a lost wakeup, so we need interrupts
1717
* to be disabled. Same goes for cv_wait_timed. */
18-
sleepq_wait(cv, __caller(0));
18+
sleepq_wait(cv, __caller(0), NULL);
1919
}
2020
_mtx_lock(m, __caller(0));
2121
}
@@ -25,7 +25,7 @@ int cv_wait_timed(condvar_t *cv, mtx_t *m, systime_t timeout) {
2525
WITH_INTR_DISABLED {
2626
cv->waiters++;
2727
mtx_unlock(m);
28-
status = sleepq_wait_timed(cv, __caller(0), timeout);
28+
status = sleepq_wait_timed(cv, __caller(0), NULL, timeout);
2929
}
3030
_mtx_lock(m, __caller(0));
3131
return status;

sys/kern/interrupt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ static void intr_thread(void *arg) {
275275
if (!TAILQ_EMPTY(&ie->ie_handlers))
276276
ie_enable(ie);
277277

278-
sleepq_wait(ie, NULL);
278+
sleepq_wait(ie, NULL, NULL);
279279
}
280280
}
281281
}

sys/kern/signal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) {
195195
}
196196

197197
int error;
198-
error = sleepq_wait_intr(&td->td_sigmask, "sigsuspend()");
198+
error = sleepq_wait_intr(&td->td_sigmask, "sigsuspend()", NULL);
199199
assert(error == EINTR);
200200

201201
return ERESTARTNOHAND;

sys/kern/sleepq.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,39 +274,49 @@ bool sleepq_abort(thread_t *td) {
274274
return _sleepq_abort(td, EINTR);
275275
}
276276

277-
void sleepq_wait(void *wchan, const void *waitpt) {
277+
void sleepq_wait(void *wchan, const void *waitpt, mtx_t *mtx) {
278278
thread_t *td = thread_self();
279279

280280
if (waitpt == NULL)
281281
waitpt = __caller(0);
282282

283283
sleepq_chain_t *sc = sc_acquire(wchan);
284+
if (mtx)
285+
mtx_unlock(mtx);
284286
mtx_lock(td->td_lock);
285287
td->td_state = TDS_SLEEPING;
286288
sq_enter(td, sc, wchan, waitpt);
287289

288290
/* Panic if we were interrupted by timeout or signal. */
289291
assert((td->td_flags & (TDF_SLPINTR | TDF_SLPTIMED)) == 0);
292+
293+
if (mtx)
294+
mtx_lock(mtx);
290295
}
291296

292297
static void sq_timeout(thread_t *td) {
293298
_sleepq_abort(td, ETIMEDOUT);
294299
}
295300

296-
int sleepq_wait_timed(void *wchan, const void *waitpt, systime_t timeout) {
301+
int sleepq_wait_timed(void *wchan, const void *waitpt, mtx_t *mtx,
302+
systime_t timeout) {
297303
thread_t *td = thread_self();
304+
int error = 0;
298305

299306
if (waitpt == NULL)
300307
waitpt = __caller(0);
301308

302309
sleepq_chain_t *sc = sc_acquire(wchan);
310+
if (mtx)
311+
mtx_unlock(mtx);
303312
mtx_lock(td->td_lock);
304313

305314
/* If there are pending signals, interrupt the sleep immediately. */
306315
if ((td->td_flags & TDF_NEEDSIGCHK) && (timeout == 0)) {
307316
mtx_unlock(td->td_lock);
308317
sc_release(sc);
309-
return EINTR;
318+
error = EINTR;
319+
goto end;
310320
}
311321

312322
if (timeout > 0) {
@@ -320,7 +330,6 @@ int sleepq_wait_timed(void *wchan, const void *waitpt, systime_t timeout) {
320330
/* After wakeup, only one of the following flags may be set:
321331
* - TDF_SLPINTR if sleep was aborted,
322332
* - TDF_SLPTIMED if sleep has timed out. */
323-
int error = 0;
324333
WITH_MTX_LOCK (td->td_lock) {
325334
if (td->td_flags & TDF_SLPINTR) {
326335
error = EINTR;
@@ -333,5 +342,8 @@ int sleepq_wait_timed(void *wchan, const void *waitpt, systime_t timeout) {
333342
if (timeout > 0)
334343
callout_stop(&td->td_slpcallout);
335344

345+
end:
346+
if (mtx)
347+
mtx_lock(mtx);
336348
return error;
337349
}

sys/kern/time.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ int do_clock_nanosleep(clockid_t clk, int flags, timespec_t *rqtp,
8989
}
9090

9191
do {
92-
error = sleepq_wait_timed((void *)(&rmt_start), __caller(0), timo);
92+
error = sleepq_wait_timed((void *)(&rmt_start), __caller(0), NULL, timo);
9393
if (error == ETIMEDOUT)
9494
goto timedout;
9595

sys/tests/sleepq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ static void test_thread(void *expected) {
1212
WITH_NO_PREEMPTION {
1313
wakeups++;
1414
}
15-
sleepq_wait(&test_thread, NULL);
15+
sleepq_wait(&test_thread, NULL, NULL);
1616
}
1717
}
1818

sys/tests/sleepq_abort.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static volatile int interrupted;
3535
* when waiters can't.
3636
* Therefore there should be only one waiter active at once */
3737
static void waiter_routine(void *_arg) {
38-
int rsn = sleepq_wait_intr(&some_val, __caller(0));
38+
int rsn = sleepq_wait_intr(&some_val, __caller(0), NULL);
3939

4040
if (rsn == EINTR)
4141
interrupted++;

sys/tests/sleepq_timed.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static thread_t *waker;
3434

3535
static void waiter_routine(void *_arg) {
3636
systime_t before_sleep = getsystime();
37-
int status = sleepq_wait_timed(&wchan, __caller(0), SLEEP_TICKS);
37+
int status = sleepq_wait_timed(&wchan, __caller(0), NULL, SLEEP_TICKS);
3838
systime_t after_sleep = getsystime();
3939
systime_t diff = after_sleep - before_sleep;
4040

sys/tests/thread_stats.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ static void thread_wake_function(void *arg) {
5353
}
5454

5555
static void thread_sleep_function(void *arg) {
56-
sleepq_wait(arg, "Thread stats test sleepq");
56+
sleepq_wait(arg, "Thread stats test sleepq", NULL);
5757
bintime_t end = *(bintime_t *)arg;
5858
bintime_add_frac(&end, test_time_frac);
5959
bintime_t now = binuptime();
6060
while (bintime_cmp(&now, &end, <)) {
61-
sleepq_wait(arg, "Thread stats test sleepq");
61+
sleepq_wait(arg, "Thread stats test sleepq", NULL);
6262
now = binuptime();
6363
}
6464
}

sys/tests/turnstile_adjust.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static int test_turnstile_adjust(void) {
8383
for (int i = 0; i < T; i++) {
8484
WITH_NO_PREEMPTION {
8585
sched_add(threads[i]);
86-
sleepq_wait(threads[i], "thread start");
86+
sleepq_wait(threads[i], "thread start", NULL);
8787
}
8888
}
8989

0 commit comments

Comments
 (0)