// // Copyright 2020 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this // file was obtained (LICENSE.txt). A copy of the license may also be // found online at https://opensource.org/licenses/MIT. // // POSIX atomics. #include "core/nng_impl.h" #ifdef NNG_PLATFORM_POSIX #ifdef NNG_HAVE_STDATOMIC #include bool nni_atomic_flag_test_and_set(nni_atomic_flag *f) { return (atomic_flag_test_and_set(&f->f)); } void nni_atomic_flag_reset(nni_atomic_flag *f) { atomic_flag_clear(&f->f); } void nni_atomic_set_bool(nni_atomic_bool *v, bool b) { atomic_store(&v->v, b); } bool nni_atomic_get_bool(nni_atomic_bool *v) { return (atomic_load(&v->v)); } bool nni_atomic_swap_bool(nni_atomic_bool *v, bool b) { return (atomic_exchange(&v->v, b)); } void nni_atomic_init_bool(nni_atomic_bool *v) { atomic_init(&v->v, false); } void nni_atomic_init(nni_atomic_int *v) { atomic_init(&v->v, 0); } void nni_atomic_add(nni_atomic_int *v, int bump) { (void) atomic_fetch_add_explicit(&v->v, bump, memory_order_relaxed); } void nni_atomic_sub(nni_atomic_int *v, int bump) { (void) atomic_fetch_sub_explicit(&v->v, bump, memory_order_relaxed); } int nni_atomic_get(nni_atomic_int *v) { return (atomic_load(&v->v)); } void nni_atomic_set(nni_atomic_int *v, int i) { return (atomic_store(&v->v, i)); } int nni_atomic_swap(nni_atomic_int *v, int i) { return (atomic_exchange(&v->v, i)); } void nni_atomic_inc(nni_atomic_int *v) { atomic_fetch_add(&v->v, 1); } void nni_atomic_dec(nni_atomic_int *v) { atomic_fetch_sub(&v->v, 1); } int nni_atomic_dec_nv(nni_atomic_int *v) { return (atomic_fetch_sub(&v->v, 1) - 1); } bool nni_atomic_cas(nni_atomic_int *v, int comp, int new) { return (atomic_compare_exchange_strong(&v->v, &comp, new)); } void nni_atomic_add64(nni_atomic_u64 *v, uint64_t bump) { (void) atomic_fetch_add_explicit( &v->v, (uint_fast64_t) bump, memory_order_relaxed); } void nni_atomic_sub64(nni_atomic_u64 *v, uint64_t bump) { (void) atomic_fetch_sub_explicit( &v->v, (uint_fast64_t) bump, memory_order_relaxed); } uint64_t nni_atomic_get64(nni_atomic_u64 *v) { return ((uint64_t) atomic_load(&v->v)); } void nni_atomic_set64(nni_atomic_u64 *v, uint64_t u) { atomic_store(&v->v, (uint_fast64_t) u); } uint64_t nni_atomic_swap64(nni_atomic_u64 *v, uint64_t u) { return ((uint64_t) atomic_exchange(&v->v, (uint_fast64_t) u)); } void nni_atomic_init64(nni_atomic_u64 *v) { atomic_init(&v->v, 0); } void nni_atomic_inc64(nni_atomic_u64 *v) { atomic_fetch_add(&v->v, 1); } uint64_t nni_atomic_dec64_nv(nni_atomic_u64 *v) { uint64_t ov; // C11 atomics give the old rather than new value. ov = (uint64_t) atomic_fetch_sub(&v->v, 1); return (ov - 1); } bool nni_atomic_cas64(nni_atomic_u64 *v, uint64_t comp, uint64_t new) { // It's possible that uint_fast64_t is not the same type underneath // as uint64_t. (Would be unusual!) uint_fast64_t cv = (uint_fast64_t) comp; uint_fast64_t nv = (uint_fast64_t) new; return (atomic_compare_exchange_strong(&v->v, &cv, nv)); } #else #include static pthread_mutex_t plat_atomic_lock = PTHREAD_MUTEX_INITIALIZER; bool nni_atomic_flag_test_and_set(nni_atomic_flag *f) { bool v; pthread_mutex_lock(&plat_atomic_lock); v = f->f; f->f = true; pthread_mutex_unlock(&plat_atomic_lock); return (v); } void nni_atomic_flag_reset(nni_atomic_flag *f) { pthread_mutex_lock(&plat_atomic_lock); f->f = false; pthread_mutex_unlock(&plat_atomic_lock); } void nni_atomic_set_bool(nni_atomic_bool *b, bool n) { pthread_mutex_lock(&plat_atomic_lock); b->b = n; pthread_mutex_unlock(&plat_atomic_lock); } bool nni_atomic_get_bool(nni_atomic_bool *b) { bool v; pthread_mutex_lock(&plat_atomic_lock); v = b->b; pthread_mutex_unlock(&plat_atomic_lock); return (v); } bool nni_atomic_swap_bool(nni_atomic_bool *b, bool n) { bool v; pthread_mutex_lock(&plat_atomic_lock); v = b->b; b->b = n; pthread_mutex_unlock(&plat_atomic_lock); return (v); } void nni_atomic_init_bool(nni_atomic_bool *b) { b->b = false; } void nni_atomic_add64(nni_atomic_u64 *v, uint64_t bump) { pthread_mutex_lock(&plat_atomic_lock); v->v += bump; pthread_mutex_unlock(&plat_atomic_lock); } void nni_atomic_sub64(nni_atomic_u64 *v, uint64_t bump) { pthread_mutex_lock(&plat_atomic_lock); v->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; } void nni_atomic_inc64(nni_atomic_u64 *v) { pthread_mutex_lock(&plat_atomic_lock); v->v++; pthread_mutex_unlock(&plat_atomic_lock); } uint64_t nni_atomic_dec64_nv(nni_atomic_u64 *v) { uint64_t nv; pthread_mutex_lock(&plat_atomic_lock); v->v--; nv = v->v; pthread_mutex_unlock(&plat_atomic_lock); return (nv); } bool nni_atomic_cas64(nni_atomic_u64 *v, uint64_t comp, uint64_t new) { bool result = false; pthread_mutex_lock(&plat_atomic_lock); if (v->v == comp) { v->v = new; result = true; } pthread_mutex_unlock(&plat_atomic_lock); return (result); } void nni_atomic_init(nni_atomic_int *v) { pthread_mutex_lock(&plat_atomic_lock); v->v = 0; pthread_mutex_unlock(&plat_atomic_lock); } void nni_atomic_add(nni_atomic_int *v, int bump) { pthread_mutex_lock(&plat_atomic_lock); v->v += bump; pthread_mutex_unlock(&plat_atomic_lock); } void nni_atomic_sub(nni_atomic_int *v, int bump) { pthread_mutex_lock(&plat_atomic_lock); v->v -= bump; pthread_mutex_unlock(&plat_atomic_lock); } int nni_atomic_get(nni_atomic_int *v) { int rv; pthread_mutex_lock(&plat_atomic_lock); rv = v->v; pthread_mutex_unlock(&plat_atomic_lock); return (rv); } void nni_atomic_set(nni_atomic_int *v, int i) { pthread_mutex_lock(&plat_atomic_lock); v->v = i; pthread_mutex_unlock(&plat_atomic_lock); } int nni_atomic_swap(nni_atomic_int *v, int i) { int rv; pthread_mutex_lock(&plat_atomic_lock); rv = v->v; v->v = i; pthread_mutex_unlock(&plat_atomic_lock); return (rv); } void nni_atomic_inc(nni_atomic_int *v) { pthread_mutex_lock(&plat_atomic_lock); v->v++; pthread_mutex_unlock(&plat_atomic_lock); } void nni_atomic_dec(nni_atomic_int *v) { pthread_mutex_lock(&plat_atomic_lock); v->v--; pthread_mutex_unlock(&plat_atomic_lock); } int nni_atomic_dec_nv(nni_atomic_int *v) { int nv; pthread_mutex_lock(&plat_atomic_lock); v->v--; nv = v->v; pthread_mutex_unlock(&plat_atomic_lock); return (nv); } bool nni_atomic_cas(nni_atomic_int *v, int comp, int new) { bool result = false; pthread_mutex_lock(&plat_atomic_lock); if (v->v == comp) { v->v = new; result = true; } pthread_mutex_unlock(&plat_atomic_lock); return (result); } #endif #endif // NNG_PLATFORM_POSIX