diff options
author | Petri Savolainen <petri.savolainen@nokia.com> | 2015-09-09 13:52:25 +0300 |
---|---|---|
committer | Maxim Uvarov <maxim.uvarov@linaro.org> | 2015-12-29 14:07:51 +0300 |
commit | 100423843b013a0d1f9ab5837cdafbea5d7c527c (patch) | |
tree | 6435ff08af023db472b66ed368d9b8b5ecbdd548 /platform | |
parent | 87c4c0545032fb998f22271bb1ad26f82ba7e108 (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.inc | 1 | ||||
-rw-r--r-- | platform/linux-generic/Makefile.am | 3 | ||||
-rw-r--r-- | platform/linux-generic/include/odp/plat/rwlock_recursive_types.h | 49 | ||||
-rw-r--r-- | platform/linux-generic/include/odp/rwlock_recursive.h | 28 | ||||
-rw-r--r-- | platform/linux-generic/odp_rwlock_recursive.c | 70 |
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); +} |