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