1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#ifndef __LINUX_RCUPDATE_H
34#define __LINUX_RCUPDATE_H
35
36#ifdef __KERNEL__
37
38#include <linux/cache.h>
39#include <linux/spinlock.h>
40#include <linux/threads.h>
41#include <linux/percpu.h>
42#include <linux/cpumask.h>
43#include <linux/seqlock.h>
44
45
46
47
48
49
50struct rcu_head {
51 struct rcu_head *next;
52 void (*func)(struct rcu_head *head);
53};
54
55#define RCU_HEAD_INIT(head) { .next = NULL, .func = NULL }
56#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT(head)
57#define INIT_RCU_HEAD(ptr) do { \
58 (ptr)->next = NULL; (ptr)->func = NULL; \
59} while (0)
60
61
62
63
64struct rcu_ctrlblk {
65 long cur;
66 long completed;
67 int next_pending;
68 seqcount_t lock;
69} ____cacheline_maxaligned_in_smp;
70
71
72static inline int rcu_batch_before(long a, long b)
73{
74 return (a - b) < 0;
75}
76
77
78static inline int rcu_batch_after(long a, long b)
79{
80 return (a - b) > 0;
81}
82
83
84
85
86
87
88struct rcu_data {
89
90 long quiescbatch;
91 long qsctr;
92 long last_qsctr;
93
94 int qs_pending;
95
96
97 long batch;
98 struct rcu_head *nxtlist;
99 struct rcu_head **nxttail;
100 struct rcu_head *curlist;
101};
102
103DECLARE_PER_CPU(struct rcu_data, rcu_data);
104extern struct rcu_ctrlblk rcu_ctrlblk;
105
106#define RCU_quiescbatch(cpu) (per_cpu(rcu_data, (cpu)).quiescbatch)
107#define RCU_qsctr(cpu) (per_cpu(rcu_data, (cpu)).qsctr)
108#define RCU_last_qsctr(cpu) (per_cpu(rcu_data, (cpu)).last_qsctr)
109#define RCU_qs_pending(cpu) (per_cpu(rcu_data, (cpu)).qs_pending)
110#define RCU_batch(cpu) (per_cpu(rcu_data, (cpu)).batch)
111#define RCU_nxtlist(cpu) (per_cpu(rcu_data, (cpu)).nxtlist)
112#define RCU_curlist(cpu) (per_cpu(rcu_data, (cpu)).curlist)
113#define RCU_nxttail(cpu) (per_cpu(rcu_data, (cpu)).nxttail)
114
115static inline int rcu_pending(int cpu)
116{
117
118
119
120 if (RCU_curlist(cpu) &&
121 !rcu_batch_before(rcu_ctrlblk.completed,RCU_batch(cpu)))
122 return 1;
123
124
125 if (!RCU_curlist(cpu) && RCU_nxtlist(cpu))
126 return 1;
127
128
129 if (RCU_quiescbatch(cpu) != rcu_ctrlblk.cur || RCU_qs_pending(cpu))
130 return 1;
131
132
133 return 0;
134}
135
136#define rcu_read_lock() preempt_disable()
137#define rcu_read_unlock() preempt_enable()
138
139extern void rcu_init(void);
140extern void rcu_check_callbacks(int cpu, int user);
141extern void rcu_restart_cpu(int cpu);
142
143
144extern void FASTCALL(call_rcu(struct rcu_head *head,
145 void (*func)(struct rcu_head *head)));
146extern void synchronize_kernel(void);
147
148#endif
149#endif
150