Applications can use recursive locks to avoid deadlock from single
thread acquiring the same lock multiple times. Recursive locks
are commonly used by legacy applications.

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

diff --git a/include/odp.h b/include/odp.h
index fe1dc74..9acd1c4 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/reclock.h>
 
 #ifdef __cplusplus
 }
diff --git a/include/odp/api/reclock.h b/include/odp/api/reclock.h
new file mode 100644
index 0000000..06ea702
--- /dev/null
+++ b/include/odp/api/reclock.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive lock
+ */
+
+#ifndef ODP_API_RECLOCK_H_
+#define ODP_API_RECLOCK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup odp_synchronizers
+ *  Operations on recursive locks.
+ *  @{
+ */
+
+/**
+ * @typedef odp_reclock_t
+ * Recursive lock
+ *
+ * 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 lock.
+ *
+ * @param lock    Pointer to a lock
+ */
+void odp_reclock_init(odp_reclock_t *lock);
+
+/**
+ * Acquire recursive lock.
+ *
+ * @param lock    Pointer to a lock
+ */
+void odp_reclock_lock(odp_reclock_t *lock);
+
+/**
+ * Try to acquire recursive lock.
+ *
+ * @param lock    Pointer to a lock
+ *
+ * @retval 1 lock acquired
+ * @retval 0 lock not acquired
+ */
+int odp_reclock_trylock(odp_reclock_t *lock);
+
+/**
+ * Release recursive lock.
+ *
+ * @param lock    Pointer to a lock
+ */
+void odp_reclock_unlock(odp_reclock_t *lock);
+
+/**
+ * Check if recursive lock is locked.
+ *
+ * @param lock    Pointer to a lock
+ *
+ * @retval 1 lock is locked
+ * @retval 0 lock is not locked
+ */
+int odp_reclock_is_locked(odp_reclock_t *lock);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/Makefile.am 
b/platform/linux-generic/Makefile.am
index 765db34..b6fd611 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -32,6 +32,7 @@ odpinclude_HEADERS = \
                  $(top_srcdir)/platform/linux-generic/include/odp/pool.h \
                  $(top_srcdir)/platform/linux-generic/include/odp/queue.h \
                  $(top_srcdir)/platform/linux-generic/include/odp/random.h \
+                 $(top_srcdir)/platform/linux-generic/include/odp/reclock.h \
                  $(top_srcdir)/platform/linux-generic/include/odp/rwlock.h \
                  $(top_srcdir)/platform/linux-generic/include/odp/schedule.h \
                  
$(top_srcdir)/platform/linux-generic/include/odp/shared_memory.h \
@@ -60,6 +61,7 @@ odpplatinclude_HEADERS = \
                  
$(top_srcdir)/platform/linux-generic/include/odp/plat/packet_io_types.h \
                  
$(top_srcdir)/platform/linux-generic/include/odp/plat/pool_types.h \
                  
$(top_srcdir)/platform/linux-generic/include/odp/plat/queue_types.h \
+                 
$(top_srcdir)/platform/linux-generic/include/odp/plat/reclock_types.h \
                  
$(top_srcdir)/platform/linux-generic/include/odp/plat/rwlock_types.h \
                  
$(top_srcdir)/platform/linux-generic/include/odp/plat/schedule_types.h \
                  
$(top_srcdir)/platform/linux-generic/include/odp/plat/shared_memory_types.h \
@@ -94,6 +96,7 @@ odpapiinclude_HEADERS = \
                  $(top_srcdir)/include/odp/api/pool.h \
                  $(top_srcdir)/include/odp/api/queue.h \
                  $(top_srcdir)/include/odp/api/random.h \
+                 $(top_srcdir)/include/odp/api/reclock.h \
                  $(top_srcdir)/include/odp/api/rwlock.h \
                  $(top_srcdir)/include/odp/api/schedule.h \
                  $(top_srcdir)/include/odp/api/shared_memory.h \
@@ -162,6 +165,7 @@ __LIB__libodp_la_SOURCES = \
                           odp_pool.c \
                           odp_queue.c \
                           ../../helper/ring.c \
+                          odp_reclock.c \
                           odp_rwlock.c \
                           odp_schedule.c \
                           odp_shared_memory.c \
diff --git a/platform/linux-generic/include/odp/plat/reclock_types.h 
b/platform/linux-generic/include/odp/plat/reclock_types.h
new file mode 100644
index 0000000..07ec0b9
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/reclock_types.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive lock
+ */
+
+#ifndef ODP_RECLOCK_TYPES_H_
+#define ODP_RECLOCK_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/spinlock.h>
+
+/**
+ * @internal
+ * ODP recursive lock
+ */
+struct odp_reclock_s {
+       odp_spinlock_t lock; /**< the lock */
+       int owner;           /**< thread inside the lock */
+       int num;             /**< number of times locked */
+};
+
+/** @addtogroup odp_synchronizers
+ *  @{
+ */
+
+typedef struct odp_reclock_s odp_reclock_t;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/reclock.h 
b/platform/linux-generic/include/odp/reclock.h
new file mode 100644
index 0000000..3f46f51
--- /dev/null
+++ b/platform/linux-generic/include/odp/reclock.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP resursive lock
+ */
+
+#ifndef ODP_PLAT_RECLOCK_H_
+#define ODP_PLAT_RECLOCK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/plat/reclock_types.h>
+
+#include <odp/api/reclock.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/odp_reclock.c 
b/platform/linux-generic/odp_reclock.c
new file mode 100644
index 0000000..101ebed
--- /dev/null
+++ b/platform/linux-generic/odp_reclock.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/reclock.h>
+#include <odp/thread.h>
+
+#define NO_OWNER (-1)
+
+void odp_reclock_init(odp_reclock_t *reclock)
+{
+       odp_spinlock_init(&reclock->lock);
+       reclock->owner = NO_OWNER;
+       reclock->num   = 0;
+}
+
+void odp_reclock_lock(odp_reclock_t *reclock)
+{
+       int thr = odp_thread_id();
+
+       if (reclock->owner == thr) {
+               reclock->num++;
+               return;
+       }
+
+       odp_spinlock_lock(&reclock->lock);
+       reclock->owner = thr;
+       reclock->num   = 1;
+}
+
+int odp_reclock_trylock(odp_reclock_t *reclock)
+{
+       int thr = odp_thread_id();
+
+       if (reclock->owner == thr) {
+               reclock->num++;
+               return 1;
+       }
+
+       if (odp_spinlock_trylock(&reclock->lock)) {
+               reclock->owner = thr;
+               reclock->num   = 1;
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+void odp_reclock_unlock(odp_reclock_t *reclock)
+{
+       reclock->num--;
+
+       if (reclock->num > 0)
+               return;
+
+       reclock->owner = NO_OWNER;
+       odp_spinlock_unlock(&reclock->lock);
+}
+
+int odp_reclock_is_locked(odp_reclock_t *reclock)
+{
+       int thr = odp_thread_id();
+
+       if (reclock->owner == thr)
+               return 1;
+
+       return odp_spinlock_is_locked(&reclock->lock);
+}
-- 
2.4.5

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

Reply via email to