From 84a1e7455c158441dd7b33d2eb296cc33dd5a6df Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 25 Aug 2018 11:41:44 -0700 Subject: fixes #674 want 64-bit atomics (for stats) --- src/core/platform.h | 9 ++++ src/platform/posix/posix_atomic.c | 89 +++++++++++++++++++++++++++++++++++++++ src/platform/posix/posix_impl.h | 10 +++++ src/platform/windows/win_impl.h | 4 ++ src/platform/windows/win_thread.c | 38 +++++++++++++++++ 5 files changed, 150 insertions(+) diff --git a/src/core/platform.h b/src/core/platform.h index 48f1e1a7..0a0709d1 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -163,6 +163,15 @@ typedef struct nni_atomic_flag nni_atomic_flag; extern bool nni_atomic_flag_test_and_set(nni_atomic_flag *); extern void nni_atomic_flag_reset(nni_atomic_flag *); +typedef struct nni_atomic_u64 nni_atomic_u64; + +extern void nni_atomic_init64(nni_atomic_u64 *); +extern void nni_atomic_inc64(nni_atomic_u64 *, uint64_t); +extern void nni_atomic_dec64(nni_atomic_u64 *, uint64_t); +extern uint64_t nni_atomic_get64(nni_atomic_u64 *); +extern void nni_atomic_set64(nni_atomic_u64 *, uint64_t); +extern uint64_t nni_atomic_swap64(nni_atomic_u64 *, uint64_t); + // // Clock Support // diff --git a/src/platform/posix/posix_atomic.c b/src/platform/posix/posix_atomic.c index a8d2579d..7f735ec0 100644 --- a/src/platform/posix/posix_atomic.c +++ b/src/platform/posix/posix_atomic.c @@ -28,6 +28,43 @@ nni_atomic_flag_reset(nni_atomic_flag *f) { atomic_flag_clear(&f->f); } + +void +nni_atomic_inc64(nni_atomic_u64 *v, uint64_t bump) +{ + (void) atomic_fetch_add_explicit(&v->v, bump, memory_order_relaxed); +} + +void +nni_atomic_dec64(nni_atomic_u64 *v, uint64_t bump) +{ + (void) atomic_fetch_sub_explicit(&v->v, bump, memory_order_relaxed); +} + +uint64_t +nni_atomic_get64(nni_atomic_u64 *v) +{ + return (atomic_load(&v->v)); +} + +void +nni_atomic_set64(nni_atomic_u64 *v, uint64_t u) +{ + atomic_store(&v->v, u); +} + +uint64_t +nni_atomic_swap64(nni_atomic_u64 *v, uint64_t u) +{ + return (atomic_exchange(&v->v, u)); +} + +void +nni_atomic_init64(nni_atomic_u64 *v) +{ + atomic_init(&v->v, 0); +} + #else #include @@ -52,6 +89,58 @@ nni_atomic_flag_reset(nni_atomic_flag *f) f->f = false; pthread_mutex_unlock(&plat_atomic_lock); } + +void +nni_atomic_inc64(nni_atomic_u64 *v, uint64_t bump) +{ + pthread_mutex_lock(&plat_atomic_lock); + v += bump; + pthread_mutex_unlock(&plat_atomic_lock); +} + +void +nni_atomic_dec64(nni_atomic_u64 *v, uint64_t bump) +{ + pthread_mutex_lock(&plat_atomic_lock); + v -= bump; + pthread_mutex_unlock(&plat_atomic_lock); +} + +uint64_t +nni_atomic_get64(nni_atomic_u64 *v) +{ + uint64_t rv; + pthread_mutex_lock(&plat_atomic_lock); + rv = v->v; + pthread_mutex_unlock(&plat_atomic_lock); + return (rv); +} + +void +nni_atomic_set64(nni_atomic_u64 *v, uint64_t u) +{ + pthread_mutex_lock(&plat_atomic_lock); + v->v = u; + pthread_mutex_unlock(&plat_atomic_lock); +} + +uint64_t +nni_atomic_swap64(nni_atomic_u64 *v, uint64_t u) +{ + uint64_t rv; + pthread_mutex_lock(&plat_atomic_lock); + rv = v->v; + v->v = u; + pthread_mutex_unlock(&plat_atomic_lock); + return (rv); +} + +void +nni_atomic_init64(nni_atomic_u64 *v) +{ + v->v = 0; +} + #endif #endif // NNG_PLATFORM_POSIX diff --git a/src/platform/posix/posix_impl.h b/src/platform/posix/posix_impl.h index 70a3615f..9f3b775b 100644 --- a/src/platform/posix/posix_impl.h +++ b/src/platform/posix/posix_impl.h @@ -82,10 +82,20 @@ struct nni_plat_flock { struct nni_atomic_flag { atomic_flag f; }; + +struct nni_atomic_u64 { + _Atomic unsigned long long v; +}; + #else // NNG_HAVE_C11_ATOMIC struct nni_atomic_flag { bool f; }; + +struct nni_atomic_flag { + uint64_t v; +}; + #endif #endif diff --git a/src/platform/windows/win_impl.h b/src/platform/windows/win_impl.h index 2cdff1c0..462e1707 100644 --- a/src/platform/windows/win_impl.h +++ b/src/platform/windows/win_impl.h @@ -52,6 +52,10 @@ struct nni_atomic_flag { unsigned f; }; +struct nni_atomic_u64 { + LONGLONG v; +}; + // nni_win_io is used with io completion ports. This allows us to get // to a specific completion callback without requiring the poller (in the // completion port) to know anything about the event itself. diff --git a/src/platform/windows/win_thread.c b/src/platform/windows/win_thread.c index b9743c5e..f80c8e3f 100644 --- a/src/platform/windows/win_thread.c +++ b/src/platform/windows/win_thread.c @@ -121,6 +121,44 @@ nni_atomic_flag_reset(nni_atomic_flag *f) InterlockedExchange(&f->f, 0); } +void +nni_atomic_inc64(nni_atomic_u64 *v, uint64_t bump) +{ + InterlockedAddNoFence64(&v->v, (LONGLONG) bump); +} + +void +nni_atomic_dec64(nni_atomic_u64 *v, uint64_t bump) +{ + // Windows lacks a sub, so we add the negative. + InterlockedAddNoFence64(&v->v, (0ll - (LONGLONG) bump)); +} + +uint64_t +nni_atomic_get64(nni_atomic_u64 *v) +{ + + return ((uint64_t)(InterlockedExchangeAdd64(&v->v, 0))); +} + +void +nni_atomic_set64(nni_atomic_u64 *v, uint64_t u) +{ + return (InterlockedExchange64(&v->v, (LONGLONG) u)); +} + +uint64_t +nni_atomic_swap64(nni_atomic_u64 *v, uint64_t u) +{ + return ((uint64_t)(InterlockedExchange64(&v->v, (LONGLONG) u))); +} + +void +nni_atomic_init64(nni_atomic_u64 *v) +{ + InterlockedExchange64(&v->v, 0); +} + static unsigned int __stdcall nni_plat_thr_main(void *arg) { nni_plat_thr *thr = arg; -- cgit v1.2.3-70-g09d2