Created
April 20, 2024 21:51
-
-
Save heatd/739d1775ec380d0247d63362ff8a3208 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 7fd3eae6b5b1872c683b4559865e9657a8196987 Mon Sep 17 00:00:00 2001 | |
From: Pedro Falcato <pedro.falcato@gmail.com> | |
Date: Sat, 20 Apr 2024 22:48:16 +0100 | |
Subject: [PATCH] mm: Re-set WAITERS after wakeup | |
Make sure WAITERS is set after wakeup. This avoids nasty races like: | |
T0 | T1 | T2 | |
Wakes up because of WAITERS && !WRITEBACK | | | |
| Grab q lock | Waiting for q lock | |
| See waiters unset | | |
| Q clear, unset WAITERS | | |
| Release Q lock | | |
Start writeback (WRITEBACK=1) | | | |
| | Grab q lock | |
| | WRITEBACK = 1 | |
| | back to sleep in the q, WAITERS = 0 | |
Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com> | |
--- | |
kernel/kernel/mm/page.cpp | 18 ++++++++++++++++++ | |
1 file changed, 18 insertions(+) | |
diff --git a/kernel/kernel/mm/page.cpp b/kernel/kernel/mm/page.cpp | |
index 33b6091a..5c76d1ad 100644 | |
--- a/kernel/kernel/mm/page.cpp | |
+++ b/kernel/kernel/mm/page.cpp | |
@@ -232,6 +232,24 @@ int page_wait_bit(struct page *p, unsigned int bit, bool interruptible) NO_THREA | |
flags = spin_lock_irqsave(&wq->lock); | |
__wait_queue_remove(wq, &token); | |
set_current_state(state); | |
+ /* clang-format off */ | |
+ /* Re-set WAITERS. WAITERS is serialized by the queue lock. This makes sure that we cannot | |
+ * have a case where we sleep and check_cond under the lock without it set, which can happen if e.g: | |
+ * T0 | T1 | T2 | |
+ * Wakes up because of WAITERS && !WRITEBACK | | | |
+ * | Grab q lock | Waiting for q lock | |
+ * | See waiters unset | | |
+ * | Q clear, unset WAITERS | | |
+ * | Release Q lock | | |
+ * Start writeback (WRITEBACK=1) | | | |
+ * | | Grab q lock | |
+ * | | WRITEBACK = 1 | |
+ * | | back to sleep in the q, WAITERS = 0 | |
+ * | |
+ * In this case, T2 hangs. This can also happen for page locks and other bits. | |
+ */ | |
+ /* clang-format on */ | |
+ page_set_waiters(p); | |
// XXX: wait_queue_remove zeroes token.context. Why? | |
token.context = &winfo; | |
__wait_queue_add(wq, &token); | |
-- | |
2.44.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment