aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/include/odp/api/plat/rwlock_recursive_inlines.h
blob: ab9a03e2114d18d836d88a0679b4e1ed85f1b8e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright (c) 2013-2018 Linaro Limited
 * Copyright (c) 2022 Nokia
 */

#ifndef ODP_PLAT_RWLOCK_RECURSIVE_INLINES_H_
#define ODP_PLAT_RWLOCK_RECURSIVE_INLINES_H_

#include <odp/api/rwlock.h>
#include <odp/api/thread.h>

#include <odp/api/abi/rwlock_recursive.h>

#include <odp/api/plat/debug_inlines.h>

#include <stdint.h>
#include <string.h>

/** @cond _ODP_HIDE_FROM_DOXYGEN_ */

#ifndef _ODP_NO_INLINE
	/* Inline functions by default */
	#define _ODP_INLINE static inline
	#define odp_rwlock_recursive_init __odp_rwlock_recursive_init
	#define odp_rwlock_recursive_read_lock __odp_rwlock_recursive_read_lock
	#define odp_rwlock_recursive_read_trylock __odp_rwlock_recursive_read_trylock
	#define odp_rwlock_recursive_read_unlock __odp_rwlock_recursive_read_unlock
	#define odp_rwlock_recursive_write_lock __odp_rwlock_recursive_write_lock
	#define odp_rwlock_recursive_write_trylock __odp_rwlock_recursive_write_trylock
	#define odp_rwlock_recursive_write_unlock __odp_rwlock_recursive_write_unlock
#else
	#undef _ODP_INLINE
	#define _ODP_INLINE
#endif

_ODP_INLINE 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 = -1;
}

/* Multiple readers can recurse the lock concurrently */
_ODP_INLINE void odp_rwlock_recursive_read_lock(odp_rwlock_recursive_t *rlock)
{
	int thr = odp_thread_id();

	if (rlock->rd_cnt[thr]) {
		_ODP_ASSERT(rlock->rd_cnt[thr] < UINT8_MAX);
		rlock->rd_cnt[thr]++;
		return;
	}

	odp_rwlock_read_lock(&rlock->lock);
	rlock->rd_cnt[thr] = 1;
}

/* Multiple readers can recurse the lock concurrently */
_ODP_INLINE int odp_rwlock_recursive_read_trylock(odp_rwlock_recursive_t *rlock)
{
	int thr = odp_thread_id();

	if (rlock->rd_cnt[thr]) {
		_ODP_ASSERT(rlock->rd_cnt[thr] < UINT8_MAX);
		rlock->rd_cnt[thr]++;
		return 1;
	}

	if (odp_rwlock_read_trylock(&rlock->lock)) {
		rlock->rd_cnt[thr] = 1;
		return 1;
	}

	return 0;
}

_ODP_INLINE void odp_rwlock_recursive_read_unlock(odp_rwlock_recursive_t *rlock)
{
	int thr = odp_thread_id();

	_ODP_ASSERT(rlock->rd_cnt[thr]);
	rlock->rd_cnt[thr]--;

	if (rlock->rd_cnt[thr] > 0)
		return;

	odp_rwlock_read_unlock(&rlock->lock);
}

/* Only one writer can recurse the lock */
_ODP_INLINE void odp_rwlock_recursive_write_lock(odp_rwlock_recursive_t *rlock)
{
	int thr = odp_thread_id();

	if (rlock->wr_owner == thr) {
		_ODP_ASSERT(rlock->wr_cnt < UINT32_MAX);
		rlock->wr_cnt++;
		return;
	}

	odp_rwlock_write_lock(&rlock->lock);
	rlock->wr_owner = thr;
	rlock->wr_cnt   = 1;
}

/* Only one writer can recurse the lock */
_ODP_INLINE int odp_rwlock_recursive_write_trylock(odp_rwlock_recursive_t *rlock)
{
	int thr = odp_thread_id();

	if (rlock->wr_owner == thr) {
		_ODP_ASSERT(rlock->wr_cnt < UINT32_MAX);
		rlock->wr_cnt++;
		return 1;
	}

	if (odp_rwlock_write_trylock(&rlock->lock)) {
		rlock->wr_owner = thr;
		rlock->wr_cnt   = 1;
		return 1;
	}

	return 0;
}

_ODP_INLINE void odp_rwlock_recursive_write_unlock(odp_rwlock_recursive_t *rlock)
{
	_ODP_ASSERT(rlock->wr_cnt);
	rlock->wr_cnt--;

	if (rlock->wr_cnt > 0)
		return;

	rlock->wr_owner = -1;
	odp_rwlock_write_unlock(&rlock->lock);
}

/** @endcond */

#endif