Commit 04b670de authored by Kent Overstreet's avatar Kent Overstreet
Browse files

closures: Add closure_wait_event_timeout()



Add a closure version of wait_event_timeout(), with the same semantics.

The closure version is useful because unlike wait_event(), it allows
blocking code to run in the conditional expression.

Cc: Coly Li <colyli@suse.de>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 9205d24c
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -454,4 +454,39 @@ do { \
		__closure_wait_event(waitlist, _cond);			\
} while (0)

#define __closure_wait_event_timeout(waitlist, _cond, _until)		\
({									\
	struct closure cl;						\
	long _t;							\
									\
	closure_init_stack(&cl);					\
									\
	while (1) {							\
		closure_wait(waitlist, &cl);				\
		if (_cond) {						\
			_t = max_t(long, 1L, _until - jiffies);		\
			break;						\
		}							\
		_t = max_t(long, 0L, _until - jiffies);			\
		if (!_t)						\
			break;						\
		closure_sync_timeout(&cl, _t);				\
	}								\
	closure_wake_up(waitlist);					\
	closure_sync(&cl);						\
	_t;								\
})

/*
 * Returns 0 if timeout expired, remaining time in jiffies (at least 1) if
 * condition became true
 */
#define closure_wait_event_timeout(waitlist, _cond, _timeout)		\
({									\
	unsigned long _until = jiffies + _timeout;			\
	(_cond)								\
		? max_t(long, 1L, _until - jiffies)			\
		: __closure_wait_event_timeout(waitlist, _cond, _until);\
})

#endif /* _LINUX_CLOSURE_H */