diff options
Diffstat (limited to 'platform/linux-generic/source/odp_rwlock.c')
-rw-r--r-- | platform/linux-generic/source/odp_rwlock.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/platform/linux-generic/source/odp_rwlock.c b/platform/linux-generic/source/odp_rwlock.c new file mode 100644 index 000000000..19c58e155 --- /dev/null +++ b/platform/linux-generic/source/odp_rwlock.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_atomic.h> +#include <odp_rwlock.h> + +#include "odp_spin_internal.h" + +void odp_rwlock_init(odp_rwlock_t *rwlock) +{ + rwlock->cnt = 0; +} + +void odp_rwlock_read_lock(odp_rwlock_t *rwlock) +{ + int32_t cnt; + int is_locked = 0; + + while (is_locked == 0) { + cnt = rwlock->cnt; + /* waiting for read lock */ + if (cnt < 0) { + odp_spin(); + continue; + } + is_locked = odp_atomic_cmpset_u32( + (volatile uint32_t *)&rwlock->cnt, + cnt, cnt + 1); + } +} + +void odp_rwlock_read_unlock(odp_rwlock_t *rwlock) +{ + odp_atomic_dec_u32((odp_atomic_u32_t *)(intptr_t)&rwlock->cnt); +} + +void odp_rwlock_write_lock(odp_rwlock_t *rwlock) +{ + int32_t cnt; + int is_locked = 0; + + while (is_locked == 0) { + cnt = rwlock->cnt; + /* lock aquired, wait */ + if (cnt != 0) { + odp_spin(); + continue; + } + is_locked = odp_atomic_cmpset_u32( + (volatile uint32_t *)&rwlock->cnt, + 0, -1); + } +} + +void odp_rwlock_write_unlock(odp_rwlock_t *rwlock) +{ + odp_atomic_inc_u32((odp_atomic_u32_t *)(intptr_t)&rwlock->cnt); +} + + |