Applications can use recursive spinlocks to avoid deadlock from
single thread acquiring the same lock multiple times. Recursive
locks are used in legacy applications. ODP version of recursive
spinlock enable porting of those applications.

Signed-off-by: Petri Savolainen <petri.savolai...@nokia.com>
---
 include/odp.h                                      |  1 +
 include/odp/api/spinlock_recursive.h               | 82 ++++++++++++++++++++++
 platform/linux-generic/Makefile.am                 |  4 ++
 .../include/odp/plat/spinlock_recursive_types.h    | 46 ++++++++++++
 .../linux-generic/include/odp/spinlock_recursive.h | 28 ++++++++
 platform/linux-generic/odp_spinlock_recursive.c    | 70 ++++++++++++++++++
 6 files changed, 231 insertions(+)
 create mode 100644 include/odp/api/spinlock_recursive.h
 create mode 100644 
platform/linux-generic/include/odp/plat/spinlock_recursive_types.h
 create mode 100644 platform/linux-generic/include/odp/spinlock_recursive.h
 create mode 100644 platform/linux-generic/odp_spinlock_recursive.c

diff --git a/include/odp.h b/include/odp.h
index fe1dc74..b47ab82 100644
--- a/include/odp.h
+++ b/include/odp.h
@@ -54,6 +54,7 @@ extern "C" {
 #include <odp/random.h>
 #include <odp/errno.h>
 #include <odp/thrmask.h>
+#include <odp/spinlock_recursive.h>
 
 #ifdef __cplusplus
 }
diff --git a/include/odp/api/spinlock_recursive.h 
b/include/odp/api/spinlock_recursive.h
new file mode 100644
index 0000000..46b6be7
--- /dev/null
+++ b/include/odp/api/spinlock_recursive.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive spinlock
+ */
+
+#ifndef ODP_API_SPINLOCK_RECURSIVE_H_
+#define ODP_API_SPINLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup odp_synchronizers
+ *  Operations on recursive spinlocks.
+ *  @{
+ */
+
+/**
+ * @typedef odp_spinlock_recursive_t
+ * Recursive spinlock
+ *
+ * A thread can acquire the lock multiple times without a deadlock. To release
+ * the lock, the thread must unlock it the same number of times.
+ */
+
+/**
+ * Initialize recursive spinlock.
+ *
+ * @param lock    Pointer to a lock
+ */
+void odp_spinlock_recursive_init(odp_spinlock_recursive_t *lock);
+
+/**
+ * Acquire recursive spinlock.
+ *
+ * @param lock    Pointer to a lock
+ */
+void odp_spinlock_recursive_lock(odp_spinlock_recursive_t *lock);
+
+/**
+ * Try to acquire recursive spinlock.
+ *
+ * @param lock    Pointer to a lock
+ *
+ * @retval 1 lock acquired
+ * @retval 0 lock not acquired
+ */
+int odp_spinlock_recursive_trylock(odp_spinlock_recursive_t *lock);
+
+/**
+ * Release recursive spinlock.
+ *
+ * @param lock    Pointer to a lock
+ */
+void odp_spinlock_recursive_unlock(odp_spinlock_recursive_t *lock);
+
+/**
+ * Check if recursive spinlock is locked.
+ *
+ * @param lock    Pointer to a lock
+ *
+ * @retval 1 lock is locked
+ * @retval 0 lock is not locked
+ */
+int odp_spinlock_recursive_is_locked(odp_spinlock_recursive_t *lock);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/Makefile.am 
b/platform/linux-generic/Makefile.am
index f2c081a..6dfdf76 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -39,6 +39,7 @@ odpinclude_HEADERS = \
                  $(srcdir)/include/odp/schedule_types.h \
                  $(srcdir)/include/odp/shared_memory.h \
                  $(srcdir)/include/odp/spinlock.h \
+                 $(srcdir)/include/odp/spinlock_recursive.h \
                  $(srcdir)/include/odp/std_types.h \
                  $(srcdir)/include/odp/sync.h \
                  $(srcdir)/include/odp/system_info.h \
@@ -67,6 +68,7 @@ odpplatinclude_HEADERS = \
                  $(srcdir)/include/odp/plat/schedule_types.h \
                  $(srcdir)/include/odp/plat/shared_memory_types.h \
                  $(srcdir)/include/odp/plat/spinlock_types.h \
+                 $(srcdir)/include/odp/plat/spinlock_recursive_types.h \
                  $(srcdir)/include/odp/plat/strong_types.h \
                  $(srcdir)/include/odp/plat/thrmask_types.h \
                  $(srcdir)/include/odp/plat/ticketlock_types.h \
@@ -102,6 +104,7 @@ odpapiinclude_HEADERS = \
                  $(top_srcdir)/include/odp/api/schedule_types.h \
                  $(top_srcdir)/include/odp/api/shared_memory.h \
                  $(top_srcdir)/include/odp/api/spinlock.h \
+                 $(top_srcdir)/include/odp/api/spinlock_recursive.h \
                  $(top_srcdir)/include/odp/api/std_types.h \
                  $(top_srcdir)/include/odp/api/sync.h \
                  $(top_srcdir)/include/odp/api/system_info.h \
@@ -158,6 +161,7 @@ __LIB__libodp_la_SOURCES = \
                           odp_schedule.c \
                           odp_shared_memory.c \
                           odp_spinlock.c \
+                          odp_spinlock_recursive.c \
                           odp_system_info.c \
                           odp_thread.c \
                           odp_thrmask.c \
diff --git a/platform/linux-generic/include/odp/plat/spinlock_recursive_types.h 
b/platform/linux-generic/include/odp/plat/spinlock_recursive_types.h
new file mode 100644
index 0000000..e2715cf
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/spinlock_recursive_types.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive spinlock
+ */
+
+#ifndef ODP_SPINLOCK_RECURSIVE_TYPES_H_
+#define ODP_SPINLOCK_RECURSIVE_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/spinlock.h>
+
+/**
+ * @internal
+ * ODP recursive spinlock
+ */
+struct odp_spinlock_recursive_s {
+       odp_spinlock_t lock; /**< the lock */
+       int owner;           /**< thread owning the lock */
+       int cnt;             /**< recursion count */
+};
+
+/** @addtogroup odp_synchronizers
+ *  @{
+ */
+
+typedef struct odp_spinlock_recursive_s odp_spinlock_recursive_t;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/spinlock_recursive.h 
b/platform/linux-generic/include/odp/spinlock_recursive.h
new file mode 100644
index 0000000..e8a9968
--- /dev/null
+++ b/platform/linux-generic/include/odp/spinlock_recursive.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP resursive spinlock
+ */
+
+#ifndef ODP_PLAT_SPINLOCK_RECURSIVE_H_
+#define ODP_PLAT_SPINLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/plat/spinlock_recursive_types.h>
+
+#include <odp/api/spinlock_recursive.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/odp_spinlock_recursive.c 
b/platform/linux-generic/odp_spinlock_recursive.c
new file mode 100644
index 0000000..8ffe6b3
--- /dev/null
+++ b/platform/linux-generic/odp_spinlock_recursive.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/spinlock_recursive.h>
+#include <odp/thread.h>
+
+#define NO_OWNER (-1)
+
+void odp_spinlock_recursive_init(odp_spinlock_recursive_t *rlock)
+{
+       odp_spinlock_init(&rlock->lock);
+       rlock->owner = NO_OWNER;
+       rlock->cnt   = 0;
+}
+
+void odp_spinlock_recursive_lock(odp_spinlock_recursive_t *rlock)
+{
+       int thr = odp_thread_id();
+
+       if (rlock->owner == thr) {
+               rlock->cnt++;
+               return;
+       }
+
+       odp_spinlock_lock(&rlock->lock);
+       rlock->owner = thr;
+       rlock->cnt   = 1;
+}
+
+int odp_spinlock_recursive_trylock(odp_spinlock_recursive_t *rlock)
+{
+       int thr = odp_thread_id();
+
+       if (rlock->owner == thr) {
+               rlock->cnt++;
+               return 1;
+       }
+
+       if (odp_spinlock_trylock(&rlock->lock)) {
+               rlock->owner = thr;
+               rlock->cnt   = 1;
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+void odp_spinlock_recursive_unlock(odp_spinlock_recursive_t *rlock)
+{
+       rlock->cnt--;
+
+       if (rlock->cnt > 0)
+               return;
+
+       rlock->owner = NO_OWNER;
+       odp_spinlock_unlock(&rlock->lock);
+}
+
+int odp_spinlock_recursive_is_locked(odp_spinlock_recursive_t *rlock)
+{
+       int thr = odp_thread_id();
+
+       if (rlock->owner == thr)
+               return 1;
+
+       return odp_spinlock_is_locked(&rlock->lock);
+}
-- 
2.5.0

_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to