LCOV - code coverage report
Current view: top level - include/linux - rcuwait.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 8 10 80.0 %
Date: 2021-04-22 12:43:58 Functions: 0 0 -

          Line data    Source code
       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             :  */
      16             : struct rcuwait {
      17             :         struct task_struct __rcu *task;
      18             : };
      19             : 
      20             : #define __RCUWAIT_INITIALIZER(name)             \
      21             :         { .task = NULL, }
      22             : 
      23         374 : static inline void rcuwait_init(struct rcuwait *w)
      24             : {
      25         374 :         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             :  */
      32           0 : static inline int rcuwait_active(struct rcuwait *w)
      33             : {
      34           0 :         return !!rcu_access_pointer(w->task);
      35             : }
      36             : 
      37             : extern 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             : 
      45         201 : static inline void prepare_to_rcuwait(struct rcuwait *w)
      46             : {
      47         201 :         rcu_assign_pointer(w->task, current);
      48         201 : }
      49             : 
      50         201 : static inline void finish_rcuwait(struct rcuwait *w)
      51             : {
      52         201 :         rcu_assign_pointer(w->task, NULL);
      53         201 :         __set_current_state(TASK_RUNNING);
      54             : }
      55             : 
      56             : #define rcuwait_wait_event(w, condition, state)                         \
      57             : ({                                                                      \
      58             :         int __ret = 0;                                                  \
      59             :         prepare_to_rcuwait(w);                                          \
      60             :         for (;;) {                                                      \
      61             :                 /*                                                      \
      62             :                  * Implicit barrier (A) pairs with (B) in               \
      63             :                  * rcuwait_wake_up().                                   \
      64             :                  */                                                     \
      65             :                 set_current_state(state);                               \
      66             :                 if (condition)                                          \
      67             :                         break;                                          \
      68             :                                                                         \
      69             :                 if (signal_pending_state(state, current)) {             \
      70             :                         __ret = -EINTR;                                 \
      71             :                         break;                                          \
      72             :                 }                                                       \
      73             :                                                                         \
      74             :                 schedule();                                             \
      75             :         }                                                               \
      76             :         finish_rcuwait(w);                                              \
      77             :         __ret;                                                          \
      78             : })
      79             : 
      80             : #endif /* _LINUX_RCUWAIT_H_ */

Generated by: LCOV version 1.14