diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-23 20:54:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-29 02:24:30 -0400 |
commit | 33d91f00c73ba0012bce18c1690cb8313ca7adaa (patch) | |
tree | 71a927098b248685af4dede30d443ef73c344d16 /include/linux | |
parent | 7a9b2d59507d85569b8a456688ef40cf2ac73e48 (diff) |
net: u64_stats_fetch_begin_bh() and u64_stats_fetch_retry_bh()
- Must disable preemption in case of 32bit UP in u64_stats_fetch_begin()
and u64_stats_fetch_retry()
- Add new u64_stats_fetch_begin_bh() and u64_stats_fetch_retry_bh() for
network usage, disabling BH on 32bit UP only.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/u64_stats_sync.h | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h index b38e3a58de83..fa261a0da280 100644 --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h | |||
@@ -27,6 +27,9 @@ | |||
27 | * (On UP, there is no seqcount_t protection, a reader allowing interrupts could | 27 | * (On UP, there is no seqcount_t protection, a reader allowing interrupts could |
28 | * read partial values) | 28 | * read partial values) |
29 | * | 29 | * |
30 | * 7) For softirq uses, readers can use u64_stats_fetch_begin_bh() and | ||
31 | * u64_stats_fetch_retry_bh() helpers | ||
32 | * | ||
30 | * Usage : | 33 | * Usage : |
31 | * | 34 | * |
32 | * Stats producer (writer) should use following template granted it already got | 35 | * Stats producer (writer) should use following template granted it already got |
@@ -58,54 +61,80 @@ | |||
58 | */ | 61 | */ |
59 | #include <linux/seqlock.h> | 62 | #include <linux/seqlock.h> |
60 | 63 | ||
61 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
62 | struct u64_stats_sync { | 64 | struct u64_stats_sync { |
65 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
63 | seqcount_t seq; | 66 | seqcount_t seq; |
67 | #endif | ||
64 | }; | 68 | }; |
65 | 69 | ||
66 | static void inline u64_stats_update_begin(struct u64_stats_sync *syncp) | 70 | static void inline u64_stats_update_begin(struct u64_stats_sync *syncp) |
67 | { | 71 | { |
72 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
68 | write_seqcount_begin(&syncp->seq); | 73 | write_seqcount_begin(&syncp->seq); |
74 | #endif | ||
69 | } | 75 | } |
70 | 76 | ||
71 | static void inline u64_stats_update_end(struct u64_stats_sync *syncp) | 77 | static void inline u64_stats_update_end(struct u64_stats_sync *syncp) |
72 | { | 78 | { |
79 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
73 | write_seqcount_end(&syncp->seq); | 80 | write_seqcount_end(&syncp->seq); |
81 | #endif | ||
74 | } | 82 | } |
75 | 83 | ||
76 | static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) | 84 | static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) |
77 | { | 85 | { |
86 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
78 | return read_seqcount_begin(&syncp->seq); | 87 | return read_seqcount_begin(&syncp->seq); |
88 | #else | ||
89 | #if BITS_PER_LONG==32 | ||
90 | preempt_disable(); | ||
91 | #endif | ||
92 | return 0; | ||
93 | #endif | ||
79 | } | 94 | } |
80 | 95 | ||
81 | static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp, | 96 | static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp, |
82 | unsigned int start) | 97 | unsigned int start) |
83 | { | 98 | { |
99 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
84 | return read_seqcount_retry(&syncp->seq, start); | 100 | return read_seqcount_retry(&syncp->seq, start); |
85 | } | ||
86 | |||
87 | #else | 101 | #else |
88 | struct u64_stats_sync { | 102 | #if BITS_PER_LONG==32 |
89 | }; | 103 | preempt_enable(); |
90 | 104 | #endif | |
91 | static void inline u64_stats_update_begin(struct u64_stats_sync *syncp) | 105 | return false; |
92 | { | 106 | #endif |
93 | } | ||
94 | |||
95 | static void inline u64_stats_update_end(struct u64_stats_sync *syncp) | ||
96 | { | ||
97 | } | 107 | } |
98 | 108 | ||
99 | static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) | 109 | /* |
110 | * In case softirq handlers can update u64 counters, readers can use following helpers | ||
111 | * - SMP 32bit arches use seqcount protection, irq safe. | ||
112 | * - UP 32bit must disable BH. | ||
113 | * - 64bit have no problem atomically reading u64 values, irq safe. | ||
114 | */ | ||
115 | static unsigned int inline u64_stats_fetch_begin_bh(const struct u64_stats_sync *syncp) | ||
100 | { | 116 | { |
117 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
118 | return read_seqcount_begin(&syncp->seq); | ||
119 | #else | ||
120 | #if BITS_PER_LONG==32 | ||
121 | local_bh_disable(); | ||
122 | #endif | ||
101 | return 0; | 123 | return 0; |
124 | #endif | ||
102 | } | 125 | } |
103 | 126 | ||
104 | static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp, | 127 | static bool inline u64_stats_fetch_retry_bh(const struct u64_stats_sync *syncp, |
105 | unsigned int start) | 128 | unsigned int start) |
106 | { | 129 | { |
130 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | ||
131 | return read_seqcount_retry(&syncp->seq, start); | ||
132 | #else | ||
133 | #if BITS_PER_LONG==32 | ||
134 | local_bh_enable(); | ||
135 | #endif | ||
107 | return false; | 136 | return false; |
108 | } | ||
109 | #endif | 137 | #endif |
138 | } | ||
110 | 139 | ||
111 | #endif /* _LINUX_U64_STATS_SYNC_H */ | 140 | #endif /* _LINUX_U64_STATS_SYNC_H */ |