aboutsummaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorPetri Savolainen <petri.savolainen@nokia.com>2015-09-09 13:52:25 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2015-12-29 14:07:51 +0300
commit100423843b013a0d1f9ab5837cdafbea5d7c527c (patch)
tree6435ff08af023db472b66ed368d9b8b5ecbdd548 /platform
parent87c4c0545032fb998f22271bb1ad26f82ba7e108 (diff)
api: rwlock_recursive: added recursive rwlock
Added recursive read-write lock. It allows threads to read lock or write lock the rwlock multiple times without deadlocking. Mixing of read and write lock operations is not supported. ODP version of recursive rwlock enables porting legacy applications, which use these kind of locks. Signed-off-by: Petri Savolainen <petri.savolainen@nokia.com> Reviewed-by: Bill Fischofer <bill.fischofer@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> Conflicts: platform/linux-generic/Makefile.am
Diffstat (limited to 'platform')
-rw-r--r--platform/Makefile.inc1
-rw-r--r--platform/linux-generic/Makefile.am3
-rw-r--r--platform/linux-generic/include/odp/plat/rwlock_recursive_types.h49
-rw-r--r--platform/linux-generic/include/odp/rwlock_recursive.h28
-rw-r--r--platform/linux-generic/odp_rwlock_recursive.c70
5 files changed, 151 insertions, 0 deletions
diff --git a/platform/Makefile.inc b/platform/Makefile.inc
index cc86b993a..c97245876 100644
--- a/platform/Makefile.inc
+++ b/platform/Makefile.inc
@@ -41,6 +41,7 @@ odpapiinclude_HEADERS = \
$(top_srcdir)/include/odp/api/queue.h \
$(top_srcdir)/include/odp/api/random.h \
$(top_srcdir)/include/odp/api/rwlock.h \
+ $(top_srcdir)/include/odp/api/rwlock_recursive.h \
$(top_srcdir)/include/odp/api/schedule.h \
$(top_srcdir)/include/odp/api/schedule_types.h \
$(top_srcdir)/include/odp/api/shared_memory.h \
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 8bcd6a943..83822ca8f 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -35,6 +35,7 @@ odpinclude_HEADERS = \
$(srcdir)/include/odp/queue.h \
$(srcdir)/include/odp/random.h \
$(srcdir)/include/odp/rwlock.h \
+ $(srcdir)/include/odp/rwlock_recursive.h \
$(srcdir)/include/odp/schedule.h \
$(srcdir)/include/odp/schedule_types.h \
$(srcdir)/include/odp/shared_memory.h \
@@ -65,6 +66,7 @@ odpplatinclude_HEADERS = \
$(srcdir)/include/odp/plat/pool_types.h \
$(srcdir)/include/odp/plat/queue_types.h \
$(srcdir)/include/odp/plat/rwlock_types.h \
+ $(srcdir)/include/odp/plat/rwlock_recursive_types.h \
$(srcdir)/include/odp/plat/schedule_types.h \
$(srcdir)/include/odp/plat/shared_memory_types.h \
$(srcdir)/include/odp/plat/spinlock_types.h \
@@ -128,6 +130,7 @@ __LIB__libodp_la_SOURCES = \
odp_pool.c \
odp_queue.c \
odp_rwlock.c \
+ odp_rwlock_recursive.c \
odp_schedule.c \
odp_shared_memory.c \
odp_spinlock.c \
diff --git a/platform/linux-generic/include/odp/plat/rwlock_recursive_types.h b/platform/linux-generic/include/odp/plat/rwlock_recursive_types.h
new file mode 100644
index 000000000..ee818723a
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/rwlock_recursive_types.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive read/write lock
+ */
+
+#ifndef ODP_RWLOCK_RECURSIVE_TYPES_H_
+#define ODP_RWLOCK_RECURSIVE_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/rwlock.h>
+#include <odp/std_types.h>
+#include <odp_config_internal.h>
+
+/**
+ * @internal
+ * ODP recursive rwlock
+ */
+struct odp_rwlock_recursive_s {
+ odp_rwlock_t lock; /**< the lock */
+ int wr_owner; /**< write owner thread */
+ uint32_t wr_cnt; /**< write recursion count */
+ uint8_t rd_cnt[_ODP_INTERNAL_MAX_THREADS]; /**< read recursion count */
+};
+
+/** @addtogroup odp_synchronizers
+ * @{
+ */
+
+typedef struct odp_rwlock_recursive_s odp_rwlock_recursive_t;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/rwlock_recursive.h b/platform/linux-generic/include/odp/rwlock_recursive.h
new file mode 100644
index 000000000..e9dadc878
--- /dev/null
+++ b/platform/linux-generic/include/odp/rwlock_recursive.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP resursive read/write lock
+ */
+
+#ifndef ODP_PLAT_RWLOCK_RECURSIVE_H_
+#define ODP_PLAT_RWLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/plat/rwlock_recursive_types.h>
+
+#include <odp/api/rwlock_recursive.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/odp_rwlock_recursive.c b/platform/linux-generic/odp_rwlock_recursive.c
new file mode 100644
index 000000000..e3a383caf
--- /dev/null
+++ b/platform/linux-generic/odp_rwlock_recursive.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/rwlock_recursive.h>
+#include <odp/thread.h>
+#include <string.h>
+
+#define NO_OWNER (-1)
+
+void odp_rwlock_recursive_init(odp_rwlock_recursive_t *rlock)
+{
+ memset(rlock, 0, sizeof(odp_rwlock_recursive_t));
+ odp_rwlock_init(&rlock->lock);
+ rlock->wr_owner = NO_OWNER;
+}
+
+/* Multiple readers can recurse the lock concurrently */
+void odp_rwlock_recursive_read_lock(odp_rwlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->rd_cnt[thr]) {
+ rlock->rd_cnt[thr]++;
+ return;
+ }
+
+ odp_rwlock_read_lock(&rlock->lock);
+ rlock->rd_cnt[thr] = 1;
+}
+
+void odp_rwlock_recursive_read_unlock(odp_rwlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ rlock->rd_cnt[thr]--;
+
+ if (rlock->rd_cnt[thr] > 0)
+ return;
+
+ odp_rwlock_read_unlock(&rlock->lock);
+}
+
+/* Only one writer can recurse the lock */
+void odp_rwlock_recursive_write_lock(odp_rwlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->wr_owner == thr) {
+ rlock->wr_cnt++;
+ return;
+ }
+
+ odp_rwlock_write_lock(&rlock->lock);
+ rlock->wr_owner = thr;
+ rlock->wr_cnt = 1;
+}
+
+void odp_rwlock_recursive_write_unlock(odp_rwlock_recursive_t *rlock)
+{
+ rlock->wr_cnt--;
+
+ if (rlock->wr_cnt > 0)
+ return;
+
+ rlock->wr_owner = NO_OWNER;
+ odp_rwlock_write_unlock(&rlock->lock);
+}