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>
This commit is contained in:
parent
7a9b2d5950
commit
33d91f00c7
|
@ -27,6 +27,9 @@
|
||||||
* (On UP, there is no seqcount_t protection, a reader allowing interrupts could
|
* (On UP, there is no seqcount_t protection, a reader allowing interrupts could
|
||||||
* read partial values)
|
* read partial values)
|
||||||
*
|
*
|
||||||
|
* 7) For softirq uses, readers can use u64_stats_fetch_begin_bh() and
|
||||||
|
* u64_stats_fetch_retry_bh() helpers
|
||||||
|
*
|
||||||
* Usage :
|
* Usage :
|
||||||
*
|
*
|
||||||
* Stats producer (writer) should use following template granted it already got
|
* Stats producer (writer) should use following template granted it already got
|
||||||
|
@ -58,54 +61,80 @@
|
||||||
*/
|
*/
|
||||||
#include <linux/seqlock.h>
|
#include <linux/seqlock.h>
|
||||||
|
|
||||||
|
struct u64_stats_sync {
|
||||||
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
||||||
struct u64_stats_sync {
|
|
||||||
seqcount_t seq;
|
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
|
#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 */
|
#endif /* _LINUX_U64_STATS_SYNC_H */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user