123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #ifndef SCM_ATOMICS_INTERNAL_H
- #define SCM_ATOMICS_INTERNAL_H
- /* Copyright 2016,2018-2019
- Free Software Foundation, Inc.
- This file is part of Guile.
- Guile is free software: you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Guile is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with Guile. If not, see
- <https://www.gnu.org/licenses/>. */
- #include "scm.h"
- #ifdef HAVE_STDATOMIC_H
- #include <stdatomic.h>
- static inline uint32_t
- scm_atomic_subtract_uint32 (uint32_t *loc, uint32_t arg)
- {
- atomic_uint_least32_t *a_loc = (atomic_uint_least32_t *) loc;
- return atomic_fetch_sub (a_loc, arg);
- }
- static inline _Bool
- scm_atomic_compare_and_swap_uint32 (uint32_t *loc, uint32_t *expected,
- uint32_t desired)
- {
- atomic_uint_least32_t *a_loc = (atomic_uint_least32_t *) loc;
- return atomic_compare_exchange_weak (a_loc, expected, desired);
- }
- static inline void
- scm_atomic_set_pointer (void **loc, void *val)
- {
- atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
- atomic_store (a_loc, (uintptr_t) val);
- }
- static inline void *
- scm_atomic_ref_pointer (void **loc)
- {
- atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
- return (void *) atomic_load (a_loc);
- }
- static inline void
- scm_atomic_set_scm (SCM *loc, SCM val)
- {
- atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
- atomic_store (a_loc, SCM_UNPACK (val));
- }
- static inline SCM
- scm_atomic_ref_scm (SCM *loc)
- {
- atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
- return SCM_PACK (atomic_load (a_loc));
- }
- static inline SCM
- scm_atomic_swap_scm (SCM *loc, SCM val)
- {
- atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
- return SCM_PACK (atomic_exchange (a_loc, SCM_UNPACK (val)));
- }
- static inline SCM
- scm_atomic_compare_and_swap_scm (SCM *loc, SCM expected, SCM desired)
- {
- atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
- SCM result = expected;
- atomic_compare_exchange_strong (a_loc, (uintptr_t *) &result,
- SCM_UNPACK (desired));
- return result;
- }
- #else /* HAVE_STDATOMIC_H */
- /* Fallback implementation using locks. */
- #include "libguile/threads.h"
- static scm_i_pthread_mutex_t atomics_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
- static inline uint32_t
- scm_atomic_subtract_uint32 (uint32_t *loc, uint32_t arg)
- {
- uint32_t ret;
- scm_i_pthread_mutex_lock (&atomics_lock);
- ret = *loc;
- *loc -= arg;
- scm_i_pthread_mutex_unlock (&atomics_lock);
- return ret;
- }
- static inline int
- scm_atomic_compare_and_swap_uint32 (uint32_t *loc, uint32_t *expected,
- uint32_t desired)
- {
- int ret;
- scm_i_pthread_mutex_lock (&atomics_lock);
- if (*loc == *expected)
- {
- *loc = desired;
- ret = 1;
- }
- else
- {
- *expected = *loc;
- ret = 0;
- }
- scm_i_pthread_mutex_unlock (&atomics_lock);
- return ret;
- }
- static inline void
- scm_atomic_set_pointer (void **loc, void *val)
- {
- scm_i_pthread_mutex_lock (&atomics_lock);
- *loc = val;
- scm_i_pthread_mutex_unlock (&atomics_lock);
- }
- static inline void *
- scm_atomic_ref_pointer (void **loc)
- {
- void *ret;
- scm_i_pthread_mutex_lock (&atomics_lock);
- ret = *loc;
- scm_i_pthread_mutex_unlock (&atomics_lock);
- return ret;
- }
- static inline void
- scm_atomic_set_scm (SCM *loc, SCM val)
- {
- scm_i_pthread_mutex_lock (&atomics_lock);
- *loc = val;
- scm_i_pthread_mutex_unlock (&atomics_lock);
- }
- static inline SCM
- scm_atomic_ref_scm (SCM *loc)
- {
- SCM ret;
- scm_i_pthread_mutex_lock (&atomics_lock);
- ret = *loc;
- scm_i_pthread_mutex_unlock (&atomics_lock);
- return ret;
- }
- static inline SCM
- scm_atomic_swap_scm (SCM *loc, SCM val)
- {
- SCM ret;
- scm_i_pthread_mutex_lock (&atomics_lock);
- ret = *loc;
- *loc = val;
- scm_i_pthread_mutex_unlock (&atomics_lock);
- return ret;
- }
- static inline SCM
- scm_atomic_compare_and_swap_scm (SCM *loc, SCM expected, SCM desired)
- {
- SCM ret;
- scm_i_pthread_mutex_lock (&atomics_lock);
- if (*loc == expected)
- {
- *loc = desired;
- ret = expected;
- }
- else
- {
- ret = *loc;
- }
- scm_i_pthread_mutex_unlock (&atomics_lock);
- return ret;
- }
- #endif /* HAVE_STDATOMIC_H */
- #endif /* SCM_ATOMICS_INTERNAL_H */
|