u64-stats-sync is a simple wrapper that compiles to a 'seqlock' on
32-bit systems and is a no-op on 64-bit systems. It will be used by next
commits

Signed-off-by: Daniele Di Proietto <diproiet...@vmware.com>
Signed-off-by: Ben Pfaff <b...@nicira.com>
---
 lib/automake.mk      |   1 +
 lib/u64-stats-sync.h | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+)
 create mode 100644 lib/u64-stats-sync.h

diff --git a/lib/automake.mk b/lib/automake.mk
index abe08a8..830dcb9 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -249,6 +249,7 @@ lib_libopenvswitch_la_SOURCES = \
        lib/tnl-ports.h \
        lib/token-bucket.c \
        lib/type-props.h \
+       lib/u64-stats-sync.h \
        lib/unaligned.h \
        lib/unicode.c \
        lib/unicode.h \
diff --git a/lib/u64-stats-sync.h b/lib/u64-stats-sync.h
new file mode 100644
index 0000000..e28e5c5
--- /dev/null
+++ b/lib/u64-stats-sync.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef U64_STATS_SYNC_H
+#define U64_STATS_SYNC_H 1
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* Lightweight r/w lock to ensure consistent 64-bit updates
+ * ========================================================
+ *
+ * 32-bit systems cannot safely read/write 64-bit values from different
+ * threads, while there's no such problem for 32-bit systems. This is a simple
+ * wrapper that compiles to a 'seqlock' in 32 bits systems and has no effect
+ * when compiled on 64-bit systems.
+ *
+ * As the name suggests it is used primarily for statistics collection.
+ *
+ * It DOESN'T guarantee consistency for the whole protected region, it just
+ * allows safe 64-bit updates.
+ *
+ * See lib/seqlock.h for details about the implementation.
+ *
+ * Usage
+ * =====
+ *
+ * Writer:
+ *    uint32_t c;
+ *    c = u64_stats_write_begin(&s);
+ *    ...
+ *    write to protected region
+ *    ...
+ *    u64_stats_write_end(&s, c);
+ *
+ * Reader:
+ *     uint32_t c;
+ *     do {
+ *         c = u64_stats_read_begin(&s);
+ *         ...
+ *         read from protected region
+ *         ...
+ *     } while (!u64_stats_read_correct(&s));
+ *
+ * A reader might have to retry if there's a write in progress.
+ * A writer will never be blocked.
+ *
+ * Thread-safety
+ * =============
+ *
+ * The implementation does not support multiple concurrent writers.  If there
+ * may be more than one writer, an external form of mutual exclusion should be
+ * used.
+ *
+ * Another appropriate use case is to protect thread-local data from
+ * reader/writer concurrent access: if the data is written only by a single
+ * thread, external synchronization is unnecessary.
+ */
+
+#if UINTPTR_MAX == UINT64_MAX
+/* 64-bits system, compile to no-op */
+
+struct u64_stats_sync {
+#ifndef __GNUC__
+    /* Empty structures are not supported by every compiler. */
+    int happy_compiler;
+#endif
+};
+
+static inline uint32_t
+u64_stats_read_begin(const struct u64_stats_sync *s OVS_UNUSED)
+{
+    return 0;
+}
+
+static inline bool
+u64_stats_read_correct(const struct u64_stats_sync *s OVS_UNUSED,
+                       uint32_t c OVS_UNUSED)
+{
+    return true;
+}
+
+static inline uint32_t
+u64_stats_write_begin(struct u64_stats_sync *s OVS_UNUSED)
+{
+    return 0;
+}
+
+static inline void
+u64_stats_write_end(struct u64_stats_sync *s OVS_UNUSED,
+                    uint32_t c OVS_UNUSED)
+{
+}
+
+#else
+/* non 64-bits (32 ?) system. Compile to 'seqlock' */
+
+#include "seqlock.h"
+
+struct u64_stats_sync {
+    struct seqlock lock;
+};
+
+static inline uint32_t
+u64_stats_read_begin(const struct u64_stats_sync *s)
+{
+    return seqlock_read_begin(&s->lock);
+}
+
+static inline bool
+u64_stats_read_correct(const struct u64_stats_sync *s, uint32_t c)
+{
+    return seqlock_read_correct(&s->lock, c);
+}
+
+static inline uint32_t
+u64_stats_write_begin(struct u64_stats_sync *s)
+{
+    return seqlock_write_begin(&s->lock);
+}
+
+static inline void
+u64_stats_write_end(struct u64_stats_sync *s, uint32_t c)
+{
+    seqlock_write_end(&s->lock, c);
+}
+
+#endif
+
+#endif /* u64-stats-sync.h */
-- 
2.1.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to