From 33d91f00c73ba0012bce18c1690cb8313ca7adaa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 24 Jun 2010 00:54:06 +0000 Subject: 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 | 59 +++++++++++++++++++++++++++++++----------- 1 file 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 @@ * (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 -#if BITS_PER_LONG==32 && defined(CONFIG_SMP) struct u64_stats_sync { +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) seqcount_t seq; +#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 -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) -{ +#if BITS_PER_LONG==32 + preempt_enable(); +#endif + return false; +#endif } -static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp) +/* + * 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(const struct u64_stats_sync *syncp, +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 */ -- cgit v1.2.3-59-g8ed1b