From 100423843b013a0d1f9ab5837cdafbea5d7c527c Mon Sep 17 00:00:00 2001 From: Petri Savolainen Date: Wed, 9 Sep 2015 13:52:25 +0300 Subject: 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 Reviewed-by: Bill Fischofer Signed-off-by: Maxim Uvarov Conflicts: platform/linux-generic/Makefile.am --- platform/linux-generic/odp_rwlock_recursive.c | 70 +++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 platform/linux-generic/odp_rwlock_recursive.c (limited to 'platform/linux-generic/odp_rwlock_recursive.c') 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 +#include +#include + +#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); +} -- cgit v1.2.3