aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Savolainen <petri.savolainen@nokia.com>2016-09-15 16:39:21 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2016-09-22 19:02:36 +0300
commit5f4f2e0da6e04637b6b4bd7aa6bb4d4d32680525 (patch)
tree5ea82c0aa89e2c191443729af222fca666e0d3a4
parent92336dd2808af4826371d467588dcb81daafe4cf (diff)
linux-gen: ticketlock: inline ticketlock implementation
Moved ticketlock implementation into ticketlock_inlines.h header file, which enables inlined version to be used inside implementation and through API. Signed-off-by: Petri Savolainen <petri.savolainen@nokia.com> Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
-rw-r--r--platform/linux-generic/Makefile.am1
-rw-r--r--platform/linux-generic/include/odp/api/plat/ticketlock_inlines.h87
-rw-r--r--platform/linux-generic/odp_ticketlock.c68
3 files changed, 97 insertions, 59 deletions
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index e3c0f566c..900ac0861 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -88,6 +88,7 @@ odpapiplatinclude_HEADERS = \
$(srcdir)/include/odp/api/plat/sync_inlines.h \
$(srcdir)/include/odp/api/plat/thread_types.h \
$(srcdir)/include/odp/api/plat/thrmask_types.h \
+ $(srcdir)/include/odp/api/plat/ticketlock_inlines.h \
$(srcdir)/include/odp/api/plat/ticketlock_types.h \
$(srcdir)/include/odp/api/plat/time_types.h \
$(srcdir)/include/odp/api/plat/timer_types.h \
diff --git a/platform/linux-generic/include/odp/api/plat/ticketlock_inlines.h b/platform/linux-generic/include/odp/api/plat/ticketlock_inlines.h
new file mode 100644
index 000000000..957d22e44
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/ticketlock_inlines.h
@@ -0,0 +1,87 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * Ticketlock inline functions
+ */
+
+#ifndef _ODP_PLAT_TICKETLOCK_INLINES_H_
+#define _ODP_PLAT_TICKETLOCK_INLINES_H_
+
+#include <odp/api/ticketlock.h>
+#include <odp/api/atomic.h>
+#include <odp/api/sync.h>
+#include <odp/api/cpu.h>
+
+static inline void _odp_ticketlock_lock(odp_ticketlock_t *ticketlock)
+{
+ uint32_t ticket;
+
+ /* Take a ticket using an atomic increment of 'next_ticket'.
+ * This can be a relaxed operation but it cannot have the
+ * acquire semantics since we haven't acquired the lock yet */
+ ticket = odp_atomic_fetch_inc_u32(&ticketlock->next_ticket);
+
+ /* Spin waiting for our turn. Use load-acquire so that we acquire
+ * all stores from the previous lock owner */
+ while (ticket != odp_atomic_load_acq_u32(&ticketlock->cur_ticket))
+ odp_cpu_pause();
+}
+
+static inline int _odp_ticketlock_trylock(odp_ticketlock_t *tklock)
+{
+ /* We read 'next_ticket' and 'cur_ticket' non-atomically which should
+ * not be a problem as they are not independent of each other.
+ * 'cur_ticket' is always <= to 'next_ticket' and if we see an
+ * older value of 'cur_ticket', this only means the lock will
+ * look busy and trylock will fail. */
+ uint32_t next = odp_atomic_load_u32(&tklock->next_ticket);
+ uint32_t cur = odp_atomic_load_u32(&tklock->cur_ticket);
+ /* First check that lock is available and possible to take without
+ * spinning. */
+ if (next == cur) {
+ /* Then try to take the lock by incrementing 'next_ticket'
+ * but only if it still has the original value which is
+ * equal to 'cur_ticket'.
+ * We don't have to include 'cur_ticket' in the comparison
+ * because it cannot be larger than 'next_ticket' (only
+ * smaller if the lock is busy).
+ * If CAS fails, it means some other thread intercepted and
+ * took a ticket which means the lock is not available
+ * anymore */
+ if (odp_atomic_cas_acq_u32(&tklock->next_ticket,
+ &next, next + 1))
+ return 1;
+ }
+ return 0;
+}
+
+static inline void _odp_ticketlock_unlock(odp_ticketlock_t *ticketlock)
+{
+ /* Release the lock by incrementing 'cur_ticket'. As we are the
+ * lock owner and thus the only thread that is allowed to write
+ * 'cur_ticket', we don't need to do this with an (expensive)
+ * atomic RMW operation. Instead load-relaxed the current value
+ * and a store-release of the incremented value */
+ uint32_t cur = odp_atomic_load_u32(&ticketlock->cur_ticket);
+
+ odp_atomic_store_rel_u32(&ticketlock->cur_ticket, cur + 1);
+}
+
+static inline int _odp_ticketlock_is_locked(odp_ticketlock_t *ticketlock)
+{
+ /* Compare 'cur_ticket' with 'next_ticket'. Ideally we should read
+ * both variables atomically but the information can become stale
+ * immediately anyway so the function can only be used reliably in
+ * a quiescent system where non-atomic loads should not pose a
+ * problem */
+ return odp_atomic_load_u32(&ticketlock->cur_ticket) !=
+ odp_atomic_load_u32(&ticketlock->next_ticket);
+}
+
+#endif
diff --git a/platform/linux-generic/odp_ticketlock.c b/platform/linux-generic/odp_ticketlock.c
index 353af9af1..f18d78f57 100644
--- a/platform/linux-generic/odp_ticketlock.c
+++ b/platform/linux-generic/odp_ticketlock.c
@@ -4,10 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <odp/api/ticketlock.h>
-#include <odp/api/atomic.h>
-#include <odp/api/sync.h>
-#include <odp/api/cpu.h>
+#include <odp/api/plat/ticketlock_inlines.h>
void odp_ticketlock_init(odp_ticketlock_t *ticketlock)
{
@@ -15,69 +12,22 @@ void odp_ticketlock_init(odp_ticketlock_t *ticketlock)
odp_atomic_init_u32(&ticketlock->cur_ticket, 0);
}
-void odp_ticketlock_lock(odp_ticketlock_t *ticketlock)
+void odp_ticketlock_lock(odp_ticketlock_t *lock)
{
- uint32_t ticket;
-
- /* Take a ticket using an atomic increment of 'next_ticket'.
- * This can be a relaxed operation but it cannot have the
- * acquire semantics since we haven't acquired the lock yet */
- ticket = odp_atomic_fetch_inc_u32(&ticketlock->next_ticket);
-
- /* Spin waiting for our turn. Use load-acquire so that we acquire
- * all stores from the previous lock owner */
- while (ticket != odp_atomic_load_acq_u32(&ticketlock->cur_ticket))
- odp_cpu_pause();
+ return _odp_ticketlock_lock(lock);
}
-int odp_ticketlock_trylock(odp_ticketlock_t *tklock)
+int odp_ticketlock_trylock(odp_ticketlock_t *lock)
{
- /* We read 'next_ticket' and 'cur_ticket' non-atomically which should
- * not be a problem as they are not independent of each other.
- * 'cur_ticket' is always <= to 'next_ticket' and if we see an
- * older value of 'cur_ticket', this only means the lock will
- * look busy and trylock will fail. */
- uint32_t next = odp_atomic_load_u32(&tklock->next_ticket);
- uint32_t cur = odp_atomic_load_u32(&tklock->cur_ticket);
- /* First check that lock is available and possible to take without
- * spinning. */
- if (next == cur) {
- /* Then try to take the lock by incrementing 'next_ticket'
- * but only if it still has the original value which is
- * equal to 'cur_ticket'.
- * We don't have to include 'cur_ticket' in the comparison
- * because it cannot be larger than 'next_ticket' (only
- * smaller if the lock is busy).
- * If CAS fails, it means some other thread intercepted and
- * took a ticket which means the lock is not available
- * anymore */
- if (odp_atomic_cas_acq_u32(&tklock->next_ticket,
- &next, next + 1))
- return 1;
- }
- return 0;
+ return _odp_ticketlock_trylock(lock);
}
-void odp_ticketlock_unlock(odp_ticketlock_t *ticketlock)
+void odp_ticketlock_unlock(odp_ticketlock_t *lock)
{
- /* Release the lock by incrementing 'cur_ticket'. As we are the
- * lock owner and thus the only thread that is allowed to write
- * 'cur_ticket', we don't need to do this with an (expensive)
- * atomic RMW operation. Instead load-relaxed the current value
- * and a store-release of the incremented value */
- uint32_t cur = odp_atomic_load_u32(&ticketlock->cur_ticket);
-
- odp_atomic_store_rel_u32(&ticketlock->cur_ticket, cur + 1);
-
+ _odp_ticketlock_unlock(lock);
}
-int odp_ticketlock_is_locked(odp_ticketlock_t *ticketlock)
+int odp_ticketlock_is_locked(odp_ticketlock_t *lock)
{
- /* Compare 'cur_ticket' with 'next_ticket'. Ideally we should read
- * both variables atomically but the information can become stale
- * immediately anyway so the function can only be used reliably in
- * a quiescent system where non-atomic loads should not pose a
- * problem */
- return odp_atomic_load_u32(&ticketlock->cur_ticket) !=
- odp_atomic_load_u32(&ticketlock->next_ticket);
+ return _odp_ticketlock_is_locked(lock);
}