aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rcutiny.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-06-29 19:49:16 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-08-20 11:55:00 -0400
commita57eb940d130477a799dfb24a570ee04979c0f7f (patch)
tree5add1c135a302cf1c1a454b0620ed17eb802923b /include/linux/rcutiny.h
parent4d87ffadbba88105f33271bef5f2c79366c6a4e1 (diff)
rcu: Add a TINY_PREEMPT_RCU
Implement a small-memory-footprint uniprocessor-only implementation of preemptible RCU. This implementation uses but a single blocked-tasks list rather than the combinatorial number used per leaf rcu_node by TREE_PREEMPT_RCU, which reduces memory consumption and greatly simplifies processing. This version also takes advantage of uniprocessor execution to accelerate grace periods in the case where there are no readers. The general design is otherwise broadly similar to that of TREE_PREEMPT_RCU. This implementation is a step towards having RCU implementation driven off of the SMP and PREEMPT kernel configuration variables, which can happen once this implementation has accumulated sufficient experience. Removed ACCESS_ONCE() from __rcu_read_unlock() and added barrier() as suggested by Steve Rostedt in order to avoid the compiler-reordering issue noted by Mathieu Desnoyers (http://lkml.org/lkml/2010/8/16/183). As can be seen below, CONFIG_TINY_PREEMPT_RCU represents almost 5Kbyte savings compared to CONFIG_TREE_PREEMPT_RCU. Of course, for non-real-time workloads, CONFIG_TINY_RCU is even better. CONFIG_TREE_PREEMPT_RCU text data bss dec filename 13 0 0 13 kernel/rcupdate.o 6170 825 28 7023 kernel/rcutree.o ---- 7026 Total CONFIG_TINY_PREEMPT_RCU text data bss dec filename 13 0 0 13 kernel/rcupdate.o 2081 81 8 2170 kernel/rcutiny.o ---- 2183 Total CONFIG_TINY_RCU (non-preemptible) text data bss dec filename 13 0 0 13 kernel/rcupdate.o 719 25 0 744 kernel/rcutiny.o --- 757 Total Requested-by: Loïc Minier <loic.minier@canonical.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'include/linux/rcutiny.h')
-rw-r--r--include/linux/rcutiny.h126
1 files changed, 89 insertions, 37 deletions
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index e2e893144a84..4cc5eba41616 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -29,66 +29,51 @@
29 29
30void rcu_sched_qs(int cpu); 30void rcu_sched_qs(int cpu);
31void rcu_bh_qs(int cpu); 31void rcu_bh_qs(int cpu);
32static inline void rcu_note_context_switch(int cpu)
33{
34 rcu_sched_qs(cpu);
35}
36 32
33#ifdef CONFIG_TINY_RCU
37#define __rcu_read_lock() preempt_disable() 34#define __rcu_read_lock() preempt_disable()
38#define __rcu_read_unlock() preempt_enable() 35#define __rcu_read_unlock() preempt_enable()
36#else /* #ifdef CONFIG_TINY_RCU */
37void __rcu_read_lock(void);
38void __rcu_read_unlock(void);
39#endif /* #else #ifdef CONFIG_TINY_RCU */
39#define __rcu_read_lock_bh() local_bh_disable() 40#define __rcu_read_lock_bh() local_bh_disable()
40#define __rcu_read_unlock_bh() local_bh_enable() 41#define __rcu_read_unlock_bh() local_bh_enable()
41#define call_rcu_sched call_rcu 42extern void call_rcu_sched(struct rcu_head *head,
43 void (*func)(struct rcu_head *rcu));
42 44
43#define rcu_init_sched() do { } while (0) 45#define rcu_init_sched() do { } while (0)
44extern void rcu_check_callbacks(int cpu, int user);
45 46
46static inline int rcu_needs_cpu(int cpu) 47extern void synchronize_sched(void);
47{
48 return 0;
49}
50 48
51/* 49#ifdef CONFIG_TINY_RCU
52 * Return the number of grace periods.
53 */
54static inline long rcu_batches_completed(void)
55{
56 return 0;
57}
58 50
59/* 51#define call_rcu call_rcu_sched
60 * Return the number of bottom-half grace periods.
61 */
62static inline long rcu_batches_completed_bh(void)
63{
64 return 0;
65}
66 52
67static inline void rcu_force_quiescent_state(void) 53static inline void synchronize_rcu(void)
68{ 54{
55 synchronize_sched();
69} 56}
70 57
71static inline void rcu_bh_force_quiescent_state(void) 58static inline void synchronize_rcu_expedited(void)
72{ 59{
60 synchronize_sched(); /* Only one CPU, so pretty fast anyway!!! */
73} 61}
74 62
75static inline void rcu_sched_force_quiescent_state(void) 63static inline void rcu_barrier(void)
76{ 64{
65 rcu_barrier_sched(); /* Only one CPU, so only one list of callbacks! */
77} 66}
78 67
79extern void synchronize_sched(void); 68#else /* #ifdef CONFIG_TINY_RCU */
80 69
81static inline void synchronize_rcu(void) 70void synchronize_rcu(void);
82{ 71void rcu_barrier(void);
83 synchronize_sched(); 72void synchronize_rcu_expedited(void);
84}
85 73
86static inline void synchronize_rcu_bh(void) 74#endif /* #else #ifdef CONFIG_TINY_RCU */
87{
88 synchronize_sched();
89}
90 75
91static inline void synchronize_rcu_expedited(void) 76static inline void synchronize_rcu_bh(void)
92{ 77{
93 synchronize_sched(); 78 synchronize_sched();
94} 79}
@@ -117,15 +102,82 @@ static inline void rcu_exit_nohz(void)
117 102
118#endif /* #else #ifdef CONFIG_NO_HZ */ 103#endif /* #else #ifdef CONFIG_NO_HZ */
119 104
105#ifdef CONFIG_TINY_RCU
106
107static inline void rcu_preempt_note_context_switch(void)
108{
109}
110
120static inline void exit_rcu(void) 111static inline void exit_rcu(void)
121{ 112{
122} 113}
123 114
115static inline int rcu_needs_cpu(int cpu)
116{
117 return 0;
118}
119
124static inline int rcu_preempt_depth(void) 120static inline int rcu_preempt_depth(void)
125{ 121{
126 return 0; 122 return 0;
127} 123}
128 124
125#else /* #ifdef CONFIG_TINY_RCU */
126
127void rcu_preempt_note_context_switch(void);
128extern void exit_rcu(void);
129int rcu_preempt_needs_cpu(void);
130
131static inline int rcu_needs_cpu(int cpu)
132{
133 return rcu_preempt_needs_cpu();
134}
135
136/*
137 * Defined as macro as it is a very low level header
138 * included from areas that don't even know about current
139 * FIXME: combine with include/linux/rcutree.h into rcupdate.h.
140 */
141#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
142
143#endif /* #else #ifdef CONFIG_TINY_RCU */
144
145static inline void rcu_note_context_switch(int cpu)
146{
147 rcu_sched_qs(cpu);
148 rcu_preempt_note_context_switch();
149}
150
151extern void rcu_check_callbacks(int cpu, int user);
152
153/*
154 * Return the number of grace periods.
155 */
156static inline long rcu_batches_completed(void)
157{
158 return 0;
159}
160
161/*
162 * Return the number of bottom-half grace periods.
163 */
164static inline long rcu_batches_completed_bh(void)
165{
166 return 0;
167}
168
169static inline void rcu_force_quiescent_state(void)
170{
171}
172
173static inline void rcu_bh_force_quiescent_state(void)
174{
175}
176
177static inline void rcu_sched_force_quiescent_state(void)
178{
179}
180
129#ifdef CONFIG_DEBUG_LOCK_ALLOC 181#ifdef CONFIG_DEBUG_LOCK_ALLOC
130 182
131extern int rcu_scheduler_active __read_mostly; 183extern int rcu_scheduler_active __read_mostly;