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