aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/include/odp/api/plat/rwlock_inlines.h
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linux-generic/include/odp/api/plat/rwlock_inlines.h')
-rw-r--r--platform/linux-generic/include/odp/api/plat/rwlock_inlines.h103
1 files changed, 103 insertions, 0 deletions
diff --git a/platform/linux-generic/include/odp/api/plat/rwlock_inlines.h b/platform/linux-generic/include/odp/api/plat/rwlock_inlines.h
new file mode 100644
index 000000000..7df3727dd
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/rwlock_inlines.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2014-2018 Linaro Limited
+ * Copyright (c) 2022 Nokia
+ */
+
+#ifndef ODP_PLAT_RWLOCK_INLINES_H_
+#define ODP_PLAT_RWLOCK_INLINES_H_
+
+#include <odp/api/atomic.h>
+#include <odp/api/cpu.h>
+
+#include <odp/api/abi/rwlock.h>
+
+#include <stdint.h>
+
+/** @cond _ODP_HIDE_FROM_DOXYGEN_ */
+
+#ifndef _ODP_NO_INLINE
+ /* Inline functions by default */
+ #define _ODP_INLINE static inline
+ #define odp_rwlock_init __odp_rwlock_init
+ #define odp_rwlock_read_lock __odp_rwlock_read_lock
+ #define odp_rwlock_read_trylock __odp_rwlock_read_trylock
+ #define odp_rwlock_read_unlock __odp_rwlock_read_unlock
+ #define odp_rwlock_write_lock __odp_rwlock_write_lock
+ #define odp_rwlock_write_trylock __odp_rwlock_write_trylock
+ #define odp_rwlock_write_unlock __odp_rwlock_write_unlock
+#else
+ #undef _ODP_INLINE
+ #define _ODP_INLINE
+#endif
+
+_ODP_INLINE void odp_rwlock_init(odp_rwlock_t *rwlock)
+{
+ odp_atomic_init_u32(&rwlock->cnt, 0);
+}
+
+_ODP_INLINE void odp_rwlock_read_lock(odp_rwlock_t *rwlock)
+{
+ uint32_t cnt;
+ int is_locked = 0;
+
+ while (is_locked == 0) {
+ cnt = odp_atomic_load_u32(&rwlock->cnt);
+ /* waiting for read lock */
+ if ((int32_t)cnt < 0) {
+ odp_cpu_pause();
+ continue;
+ }
+ is_locked = odp_atomic_cas_acq_u32(&rwlock->cnt, &cnt, cnt + 1);
+ }
+}
+
+_ODP_INLINE int odp_rwlock_read_trylock(odp_rwlock_t *rwlock)
+{
+ uint32_t cnt = odp_atomic_load_u32(&rwlock->cnt);
+
+ while (cnt != (uint32_t)-1) {
+ if (odp_atomic_cas_acq_u32(&rwlock->cnt, &cnt, cnt + 1))
+ return 1;
+ }
+
+ return 0;
+}
+
+_ODP_INLINE void odp_rwlock_read_unlock(odp_rwlock_t *rwlock)
+{
+ odp_atomic_sub_rel_u32(&rwlock->cnt, 1);
+}
+
+_ODP_INLINE void odp_rwlock_write_lock(odp_rwlock_t *rwlock)
+{
+ uint32_t cnt;
+ int is_locked = 0;
+
+ while (is_locked == 0) {
+ uint32_t zero = 0;
+
+ cnt = odp_atomic_load_u32(&rwlock->cnt);
+ /* lock acquired, wait */
+ if (cnt != 0) {
+ odp_cpu_pause();
+ continue;
+ }
+ is_locked = odp_atomic_cas_acq_u32(&rwlock->cnt, &zero, (uint32_t)-1);
+ }
+}
+
+_ODP_INLINE int odp_rwlock_write_trylock(odp_rwlock_t *rwlock)
+{
+ uint32_t zero = 0;
+
+ return odp_atomic_cas_acq_u32(&rwlock->cnt, &zero, (uint32_t)-1);
+}
+
+_ODP_INLINE void odp_rwlock_write_unlock(odp_rwlock_t *rwlock)
+{
+ odp_atomic_store_rel_u32(&rwlock->cnt, 0);
+}
+
+/** @endcond */
+
+#endif