cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rcuwait.h (1795B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _LINUX_RCUWAIT_H_
      3#define _LINUX_RCUWAIT_H_
      4
      5#include <linux/rcupdate.h>
      6#include <linux/sched/signal.h>
      7
      8/*
      9 * rcuwait provides a way of blocking and waking up a single
     10 * task in an rcu-safe manner.
     11 *
     12 * The only time @task is non-nil is when a user is blocked (or
     13 * checking if it needs to) on a condition, and reset as soon as we
     14 * know that the condition has succeeded and are awoken.
     15 */
     16struct rcuwait {
     17	struct task_struct __rcu *task;
     18};
     19
     20#define __RCUWAIT_INITIALIZER(name)		\
     21	{ .task = NULL, }
     22
     23static inline void rcuwait_init(struct rcuwait *w)
     24{
     25	w->task = NULL;
     26}
     27
     28/*
     29 * Note: this provides no serialization and, just as with waitqueues,
     30 * requires care to estimate as to whether or not the wait is active.
     31 */
     32static inline int rcuwait_active(struct rcuwait *w)
     33{
     34	return !!rcu_access_pointer(w->task);
     35}
     36
     37extern int rcuwait_wake_up(struct rcuwait *w);
     38
     39/*
     40 * The caller is responsible for locking around rcuwait_wait_event(),
     41 * and [prepare_to/finish]_rcuwait() such that writes to @task are
     42 * properly serialized.
     43 */
     44
     45static inline void prepare_to_rcuwait(struct rcuwait *w)
     46{
     47	rcu_assign_pointer(w->task, current);
     48}
     49
     50extern void finish_rcuwait(struct rcuwait *w);
     51
     52#define rcuwait_wait_event(w, condition, state)				\
     53({									\
     54	int __ret = 0;							\
     55	prepare_to_rcuwait(w);						\
     56	for (;;) {							\
     57		/*							\
     58		 * Implicit barrier (A) pairs with (B) in		\
     59		 * rcuwait_wake_up().					\
     60		 */							\
     61		set_current_state(state);				\
     62		if (condition)						\
     63			break;						\
     64									\
     65		if (signal_pending_state(state, current)) {		\
     66			__ret = -EINTR;					\
     67			break;						\
     68		}							\
     69									\
     70		schedule();						\
     71	}								\
     72	finish_rcuwait(w);						\
     73	__ret;								\
     74})
     75
     76#endif /* _LINUX_RCUWAIT_H_ */