From 33d91f00c73ba0012bce18c1690cb8313ca7adaa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 24 Jun 2010 00:54:06 +0000 Subject: [PATCH] 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 Signed-off-by: David S. Miller --- include/linux/u64_stats_sync.h | 121 ++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 46 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 @@ * (On UP, there is no seqcount_t protection, a reader allowing interrupts could * read partial values) * + * 7) For softirq uses, readers can use u64_stats_fetch_begin_bh() and + * u64_stats_fetch_retry_bh() helpers + * * Usage : * * Stats producer (writer) should use following template granted it already got @@ -58,54 +61,80 @@ */ #include +struct u64_stats_sync { #if BITS_PER_LONG==32 && defined(CONFIG_SMP) -struct u64_stats_sync { seqcount_t seq; -}; - -static void inline u64_stats_update_begin(struct u64_stats_sync *syncp) -{ - write_seqcount_begin(&syncp->seq); -} - -static void inline u64_stats_update_end(struct u64_stats_sync *syncp) -{ - write_seqcount_end(&syncp->seq); -} - -static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) -{ - return read_seqcount_begin(&syncp->seq); -} - -static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp, - unsigned int start) -{ - return read_seqcount_retry(&syncp->seq, start); -} - -#else -struct u64_stats_sync { -}; - -static void inline u64_stats_update_begin(struct u64_stats_sync *syncp) -{ -} - -static void inline u64_stats_update_end(struct u64_stats_sync *syncp) -{ -} - -static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) -{ - return 0; -} - -static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp, - unsigned int start) -{ - return false; -} #endif +}; + +static void inline u64_stats_update_begin(struct u64_stats_sync *syncp) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + write_seqcount_begin(&syncp->seq); +#endif +} + +static void inline u64_stats_update_end(struct u64_stats_sync *syncp) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + write_seqcount_end(&syncp->seq); +#endif +} + +static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + return read_seqcount_begin(&syncp->seq); +#else +#if BITS_PER_LONG==32 + preempt_disable(); +#endif + return 0; +#endif +} + +static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp, + unsigned int start) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + return read_seqcount_retry(&syncp->seq, start); +#else +#if BITS_PER_LONG==32 + preempt_enable(); +#endif + return false; +#endif +} + +/* + * In case softirq handlers can update u64 counters, readers can use following helpers + * - SMP 32bit arches use seqcount protection, irq safe. + * - UP 32bit must disable BH. + * - 64bit have no problem atomically reading u64 values, irq safe. + */ +static unsigned int inline u64_stats_fetch_begin_bh(const struct u64_stats_sync *syncp) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + return read_seqcount_begin(&syncp->seq); +#else +#if BITS_PER_LONG==32 + local_bh_disable(); +#endif + return 0; +#endif +} + +static bool inline u64_stats_fetch_retry_bh(const struct u64_stats_sync *syncp, + unsigned int start) +{ +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + return read_seqcount_retry(&syncp->seq, start); +#else +#if BITS_PER_LONG==32 + local_bh_enable(); +#endif + return false; +#endif +} #endif /* _LINUX_U64_STATS_SYNC_H */