Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/drm2/linux linux: Fix wait_bit semantics.
details: https://anonhg.NetBSD.org/src/rev/2a489092d9d4
branches: trunk
changeset: 1028967:2a489092d9d4
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 12:36:08 2021 +0000
description:
linux: Fix wait_bit semantics.
- wait_on_bit is supposed to wait until the bit is cleared, not set.
- wait_on_bit_timeout is supposed to return 0 on success, -EAGAIN on
faiure.
Omit wake_up_bit; nothing uses it and clear_and_wake_up_bit is a more
semantically coherent operation.
diffstat:
sys/external/bsd/drm2/include/linux/wait_bit.h | 4 +-
sys/external/bsd/drm2/linux/linux_wait_bit.c | 113 +++++++++++++++---------
2 files changed, 71 insertions(+), 46 deletions(-)
diffs (207 lines):
diff -r 52043fb851ce -r 2a489092d9d4 sys/external/bsd/drm2/include/linux/wait_bit.h
--- a/sys/external/bsd/drm2/include/linux/wait_bit.h Sun Dec 19 12:36:02 2021 +0000
+++ b/sys/external/bsd/drm2/include/linux/wait_bit.h Sun Dec 19 12:36:08 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wait_bit.h,v 1.3 2021/12/19 11:26:50 riastradh Exp $ */
+/* $NetBSD: wait_bit.h,v 1.4 2021/12/19 12:36:08 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -35,12 +35,10 @@
#define clear_and_wake_up_bit linux_clear_and_wake_up_bit
#define wait_on_bit linux_wait_on_bit
#define wait_on_bit_timeout linux_wait_on_bit_timeout
-#define wake_up_bit linux_wake_up_bit
int linux_wait_bit_init(void);
void linux_wait_bit_fini(void);
-void wake_up_bit(const volatile unsigned long *, unsigned);
void clear_and_wake_up_bit(int, volatile unsigned long *);
int wait_on_bit(const volatile unsigned long *, unsigned, int);
int wait_on_bit_timeout(const volatile unsigned long *, unsigned, int,
diff -r 52043fb851ce -r 2a489092d9d4 sys/external/bsd/drm2/linux/linux_wait_bit.c
--- a/sys/external/bsd/drm2/linux/linux_wait_bit.c Sun Dec 19 12:36:02 2021 +0000
+++ b/sys/external/bsd/drm2/linux/linux_wait_bit.c Sun Dec 19 12:36:08 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_wait_bit.c,v 1.4 2021/12/19 11:26:50 riastradh Exp $ */
+/* $NetBSD: linux_wait_bit.c,v 1.5 2021/12/19 12:36:09 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_wait_bit.c,v 1.4 2021/12/19 11:26:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_wait_bit.c,v 1.5 2021/12/19 12:36:09 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -104,16 +104,13 @@
mutex_exit(&wbe->lock);
}
-void
-wake_up_bit(const volatile unsigned long *bitmap, unsigned bit)
-{
- struct waitbitentry *wbe;
-
- wbe = wait_bit_enter(bitmap, bit);
- cv_broadcast(&wbe->cv);
- wait_bit_exit(wbe);
-}
-
+/*
+ * clear_and_wake_up_bit(bit, bitmap)
+ *
+ * Clear the specified bit in the bitmap and wake any waiters in
+ * wait_on_bit or wait_on_bit_timeout that were waiting for it to
+ * clear.
+ */
void
clear_and_wake_up_bit(int bit, volatile unsigned long *bitmap)
{
@@ -125,38 +122,55 @@
wait_bit_exit(wbe);
}
+/*
+ * wait_on_bit(bitmap, bit, flags)
+ *
+ * Wait for the specified bit in bitmap to be cleared. Returns 0
+ * on success, -EINTR on signal, unless flags has
+ * TASK_UNINTERRUPTIBLE set.
+ */
int
wait_on_bit(const volatile unsigned long *bitmap, unsigned bit, int flags)
{
struct waitbitentry *wbe;
int error, ret;
- if (test_bit(bit, bitmap))
+ if (test_bit(bit, bitmap) == 0)
return 0;
wbe = wait_bit_enter(bitmap, bit);
- while (!test_bit(bit, bitmap)) {
+ while (test_bit(bit, bitmap)) {
if (flags & TASK_UNINTERRUPTIBLE) {
cv_wait(&wbe->cv, &wbe->lock);
} else {
error = cv_wait_sig(&wbe->cv, &wbe->lock);
- if (error == EINTR || error == ERESTART)
- ret = -ERESTARTSYS;
- else if (error != 0)
- ret = -error;
- if (ret)
+ if (error) {
+ /* cv_wait_sig can only fail on signal. */
+ KASSERTMSG(error == EINTR || error == ERESTART,
+ "error=%d", error);
+ ret = -EINTR;
goto out;
+ }
}
}
- /* Bit is set. Return zero on success. */
+ /* Bit is clear. Return zero on success. */
+ KASSERT(test_bit(bit, bitmap) == 0);
ret = 0;
-out: wait_bit_exit(wbe);
+out: KASSERT(test_bit(bit, bitmap) == 0 || ret != 0);
+ wait_bit_exit(wbe);
return ret;
}
+/*
+ * wait_on_bit_timeout(bitmap, bit, flags, timeout)
+ *
+ * Wait for the specified bit in bitmap to be cleared. Returns 0
+ * on success, -EINTR on signal unless flags has
+ * TASK_UNINTERRUPTIBLE set, or -EAGAIN on timeout.
+ */
int
wait_on_bit_timeout(const volatile unsigned long *bitmap, unsigned bit,
int flags, unsigned long timeout)
@@ -164,42 +178,55 @@
struct waitbitentry *wbe;
int error, ret;
- if (test_bit(bit, bitmap))
- return timeout;
+ if (test_bit(bit, bitmap) == 0)
+ return 0;
wbe = wait_bit_enter(bitmap, bit);
- while (!test_bit(bit, bitmap)) {
+ while (test_bit(bit, bitmap)) {
unsigned starttime, endtime;
- starttime = hardclock_ticks;
- if (flags & TASK_UNINTERRUPTIBLE) {
- error = cv_timedwait(&wbe->cv, &wbe->lock,
- MIN(INT_MAX, timeout));
- } else {
- error = cv_timedwait_sig(&wbe->cv, &wbe->lock,
- MIN(INT_MAX, timeout));
- }
- endtime = hardclock_ticks;
-
- /* If we timed out, return zero time left. */
- if (error == EWOULDBLOCK || endtime - starttime < timeout) {
- ret = 0;
+ if (timeout == 0) {
+ ret = -EAGAIN;
goto out;
}
- /* If we were interrupted, return -ERESTARTSYS. */
- if (error == EINTR || error == ERESTART) {
- ret = -ERESTARTSYS;
+ starttime = getticks();
+ if (flags & TASK_UNINTERRUPTIBLE) {
+ error = cv_timedwait(&wbe->cv, &wbe->lock,
+ MIN(timeout, INT_MAX/2));
+ } else {
+ error = cv_timedwait_sig(&wbe->cv, &wbe->lock,
+ MIN(timeout, INT_MAX/2));
+ }
+ endtime = getticks();
+
+ /*
+ * If we were interrupted or timed out, massage the
+ * error return and stop here.
+ */
+ if (error) {
+ KASSERTMSG((error == EINTR || error == ERESTART ||
+ error == EWOULDBLOCK), "error=%d", error);
+ if (error == EINTR || error == ERESTART) {
+ ret = -EINTR;
+ } else if (error == EWOULDBLOCK) {
+ ret = -EAGAIN;
+ } else {
+ panic("invalid error=%d", error);
+ }
goto out;
}
/* Otherwise, debit the time spent. */
- timeout -= (endtime - starttime);
+ timeout -= MIN(timeout, (endtime - starttime));
}
- /* Bit is set. Return the time left. */
+
+ /* Bit is clear. Return zero on success. */
+ KASSERT(test_bit(bit, bitmap) == 0);
ret = timeout;
-out: wait_bit_exit(wbe);
+out: KASSERT(test_bit(bit, bitmap) == 0 || ret != 0);
+ wait_bit_exit(wbe);
return ret;
}
Home |
Main Index |
Thread Index |
Old Index