Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Kent Overstreet <kent.overstreet@linux.dev>

+35
+35
include/linux/closure.h
··· 454 454 __closure_wait_event(waitlist, _cond); \ 455 455 } while (0) 456 456 457 + #define __closure_wait_event_timeout(waitlist, _cond, _until) \ 458 + ({ \ 459 + struct closure cl; \ 460 + long _t; \ 461 + \ 462 + closure_init_stack(&cl); \ 463 + \ 464 + while (1) { \ 465 + closure_wait(waitlist, &cl); \ 466 + if (_cond) { \ 467 + _t = max_t(long, 1L, _until - jiffies); \ 468 + break; \ 469 + } \ 470 + _t = max_t(long, 0L, _until - jiffies); \ 471 + if (!_t) \ 472 + break; \ 473 + closure_sync_timeout(&cl, _t); \ 474 + } \ 475 + closure_wake_up(waitlist); \ 476 + closure_sync(&cl); \ 477 + _t; \ 478 + }) 479 + 480 + /* 481 + * Returns 0 if timeout expired, remaining time in jiffies (at least 1) if 482 + * condition became true 483 + */ 484 + #define closure_wait_event_timeout(waitlist, _cond, _timeout) \ 485 + ({ \ 486 + unsigned long _until = jiffies + _timeout; \ 487 + (_cond) \ 488 + ? max_t(long, 1L, _until - jiffies) \ 489 + : __closure_wait_event_timeout(waitlist, _cond, _until);\ 490 + }) 491 + 457 492 #endif /* _LINUX_CLOSURE_H */