|
@@ -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 <linux/seqlock.h>
|
|
|
|
|
|
-#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 */
|