closures: closure_wait_event()
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 9 Dec 2017 17:42:44 +0000 (12:42 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 19 Oct 2023 18:47:33 +0000 (14:47 -0400)
Like wait_event() - except, because it uses closures and closure
waitlists it doesn't have the restriction on modifying task state inside
the condition check, like wait_event() does.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Acked-by: Coly Li <colyli@suse.de>
include/linux/closure.h

index 0ec9e7bc8d9734f4b4f2e50dc2fab39b398ae766..36b4a83f9b77460fada6dae5580662cec391df18 100644 (file)
@@ -374,4 +374,26 @@ static inline void closure_call(struct closure *cl, closure_fn fn,
        continue_at_nobarrier(cl, fn, wq);
 }
 
+#define __closure_wait_event(waitlist, _cond)                          \
+do {                                                                   \
+       struct closure cl;                                              \
+                                                                       \
+       closure_init_stack(&cl);                                        \
+                                                                       \
+       while (1) {                                                     \
+               closure_wait(waitlist, &cl);                            \
+               if (_cond)                                              \
+                       break;                                          \
+               closure_sync(&cl);                                      \
+       }                                                               \
+       closure_wake_up(waitlist);                                      \
+       closure_sync(&cl);                                              \
+} while (0)
+
+#define closure_wait_event(waitlist, _cond)                            \
+do {                                                                   \
+       if (!(_cond))                                                   \
+               __closure_wait_event(waitlist, _cond);                  \
+} while (0)
+
 #endif /* _LINUX_CLOSURE_H */