1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
28f95c90cSDavidlohr Bueso #ifndef _LINUX_RCUWAIT_H_
38f95c90cSDavidlohr Bueso #define _LINUX_RCUWAIT_H_
48f95c90cSDavidlohr Bueso
58f95c90cSDavidlohr Bueso #include <linux/rcupdate.h>
680fbaf1cSPeter Zijlstra (Intel) #include <linux/sched/signal.h>
7*2c2bd11cSSuren Baghdasaryan #include <linux/types.h>
88f95c90cSDavidlohr Bueso
98f95c90cSDavidlohr Bueso #define __RCUWAIT_INITIALIZER(name) \
108f95c90cSDavidlohr Bueso { .task = NULL, }
118f95c90cSDavidlohr Bueso
rcuwait_init(struct rcuwait * w)128f95c90cSDavidlohr Bueso static inline void rcuwait_init(struct rcuwait *w)
138f95c90cSDavidlohr Bueso {
148f95c90cSDavidlohr Bueso w->task = NULL;
158f95c90cSDavidlohr Bueso }
168f95c90cSDavidlohr Bueso
17191a43beSDavidlohr Bueso /*
18191a43beSDavidlohr Bueso * Note: this provides no serialization and, just as with waitqueues,
19191a43beSDavidlohr Bueso * requires care to estimate as to whether or not the wait is active.
20191a43beSDavidlohr Bueso */
rcuwait_active(struct rcuwait * w)21191a43beSDavidlohr Bueso static inline int rcuwait_active(struct rcuwait *w)
22191a43beSDavidlohr Bueso {
23febd668dSPaolo Bonzini return !!rcu_access_pointer(w->task);
24191a43beSDavidlohr Bueso }
25191a43beSDavidlohr Bueso
269d9a6ebfSDavidlohr Bueso extern int rcuwait_wake_up(struct rcuwait *w);
278f95c90cSDavidlohr Bueso
288f95c90cSDavidlohr Bueso /*
298f95c90cSDavidlohr Bueso * The caller is responsible for locking around rcuwait_wait_event(),
305c21f7b3SDavidlohr Bueso * and [prepare_to/finish]_rcuwait() such that writes to @task are
315c21f7b3SDavidlohr Bueso * properly serialized.
328f95c90cSDavidlohr Bueso */
335c21f7b3SDavidlohr Bueso
prepare_to_rcuwait(struct rcuwait * w)345c21f7b3SDavidlohr Bueso static inline void prepare_to_rcuwait(struct rcuwait *w)
355c21f7b3SDavidlohr Bueso {
365c21f7b3SDavidlohr Bueso rcu_assign_pointer(w->task, current);
375c21f7b3SDavidlohr Bueso }
385c21f7b3SDavidlohr Bueso
3958d4292bSIngo Molnar extern void finish_rcuwait(struct rcuwait *w);
405c21f7b3SDavidlohr Bueso
41f6239d3fSDavidlohr Bueso #define ___rcuwait_wait_event(w, condition, state, ret, cmd) \
428f95c90cSDavidlohr Bueso ({ \
43f6239d3fSDavidlohr Bueso long __ret = ret; \
445c21f7b3SDavidlohr Bueso prepare_to_rcuwait(w); \
458f95c90cSDavidlohr Bueso for (;;) { \
468f95c90cSDavidlohr Bueso /* \
478f95c90cSDavidlohr Bueso * Implicit barrier (A) pairs with (B) in \
487e1f9467SDavidlohr Bueso * rcuwait_wake_up(). \
498f95c90cSDavidlohr Bueso */ \
5080fbaf1cSPeter Zijlstra (Intel) set_current_state(state); \
518f95c90cSDavidlohr Bueso if (condition) \
528f95c90cSDavidlohr Bueso break; \
538f95c90cSDavidlohr Bueso \
5480fbaf1cSPeter Zijlstra (Intel) if (signal_pending_state(state, current)) { \
5580fbaf1cSPeter Zijlstra (Intel) __ret = -EINTR; \
5680fbaf1cSPeter Zijlstra (Intel) break; \
5780fbaf1cSPeter Zijlstra (Intel) } \
5880fbaf1cSPeter Zijlstra (Intel) \
59f6239d3fSDavidlohr Bueso cmd; \
608f95c90cSDavidlohr Bueso } \
615c21f7b3SDavidlohr Bueso finish_rcuwait(w); \
6280fbaf1cSPeter Zijlstra (Intel) __ret; \
638f95c90cSDavidlohr Bueso })
648f95c90cSDavidlohr Bueso
65f6239d3fSDavidlohr Bueso #define rcuwait_wait_event(w, condition, state) \
66f6239d3fSDavidlohr Bueso ___rcuwait_wait_event(w, condition, state, 0, schedule())
67f6239d3fSDavidlohr Bueso
68f6239d3fSDavidlohr Bueso #define __rcuwait_wait_event_timeout(w, condition, state, timeout) \
69f6239d3fSDavidlohr Bueso ___rcuwait_wait_event(w, ___wait_cond_timeout(condition), \
70f6239d3fSDavidlohr Bueso state, timeout, \
71f6239d3fSDavidlohr Bueso __ret = schedule_timeout(__ret))
72f6239d3fSDavidlohr Bueso
73f6239d3fSDavidlohr Bueso #define rcuwait_wait_event_timeout(w, condition, state, timeout) \
74f6239d3fSDavidlohr Bueso ({ \
75f6239d3fSDavidlohr Bueso long __ret = timeout; \
76f6239d3fSDavidlohr Bueso if (!___wait_cond_timeout(condition)) \
77f6239d3fSDavidlohr Bueso __ret = __rcuwait_wait_event_timeout(w, condition, \
78f6239d3fSDavidlohr Bueso state, timeout); \
79f6239d3fSDavidlohr Bueso __ret; \
80f6239d3fSDavidlohr Bueso })
81f6239d3fSDavidlohr Bueso
828f95c90cSDavidlohr Bueso #endif /* _LINUX_RCUWAIT_H_ */
83