1
2
3
4
5
6
7
8
9
10
11#ifndef _LINUX_SRCU_TINY_H
12#define _LINUX_SRCU_TINY_H
13
14#include <linux/swait.h>
15
16struct srcu_struct {
17 short srcu_lock_nesting[2];
18 unsigned short srcu_idx;
19 unsigned short srcu_idx_max;
20 u8 srcu_gp_running;
21 u8 srcu_gp_waiting;
22 struct swait_queue_head srcu_wq;
23
24 struct rcu_head *srcu_cb_head;
25 struct rcu_head **srcu_cb_tail;
26 struct work_struct srcu_work;
27#ifdef CONFIG_DEBUG_LOCK_ALLOC
28 struct lockdep_map dep_map;
29#endif
30};
31
32void srcu_drive_gp(struct work_struct *wp);
33
34#define __SRCU_STRUCT_INIT(name, __ignored) \
35{ \
36 .srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq), \
37 .srcu_cb_tail = &name.srcu_cb_head, \
38 .srcu_work = __WORK_INITIALIZER(name.srcu_work, srcu_drive_gp), \
39 __SRCU_DEP_MAP_INIT(name) \
40}
41
42
43
44
45
46#define DEFINE_SRCU(name) \
47 struct srcu_struct name = __SRCU_STRUCT_INIT(name, name)
48#define DEFINE_STATIC_SRCU(name) \
49 static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name)
50
51void synchronize_srcu(struct srcu_struct *ssp);
52
53
54
55
56
57
58
59static inline int __srcu_read_lock(struct srcu_struct *ssp)
60{
61 int idx;
62
63 idx = ((READ_ONCE(ssp->srcu_idx) + 1) & 0x2) >> 1;
64 WRITE_ONCE(ssp->srcu_lock_nesting[idx], ssp->srcu_lock_nesting[idx] + 1);
65 return idx;
66}
67
68static inline void synchronize_srcu_expedited(struct srcu_struct *ssp)
69{
70 synchronize_srcu(ssp);
71}
72
73static inline void srcu_barrier(struct srcu_struct *ssp)
74{
75 synchronize_srcu(ssp);
76}
77
78
79static inline void srcu_torture_stats_print(struct srcu_struct *ssp,
80 char *tt, char *tf)
81{
82 int idx;
83
84 idx = ((READ_ONCE(ssp->srcu_idx) + 1) & 0x2) >> 1;
85 pr_alert("%s%s Tiny SRCU per-CPU(idx=%d): (%hd,%hd)\n",
86 tt, tf, idx,
87 READ_ONCE(ssp->srcu_lock_nesting[!idx]),
88 READ_ONCE(ssp->srcu_lock_nesting[idx]));
89}
90
91#endif
92