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