Skip to content

Commit 2f2d728

Browse files
committed
shced:sem: replace mutex with spinlock
The overhead of spinlok is less than mutext (mutex need to call enter_critical section.) After this patch, `down_write_trylock` and `down_read_trylock` can be use in interrupt context. The instruction is protected with mutex only one instruction so using spinlock is better. Signed-off-by: TaiJu Wu <[email protected]>
1 parent e0c18c0 commit 2f2d728

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

include/nuttx/rwsem.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@
2525
* Included Files
2626
****************************************************************************/
2727

28-
#include <nuttx/mutex.h>
28+
#include <nuttx/semaphore.h>
29+
#include <nuttx/spinlock.h>
2930

3031
/****************************************************************************
3132
* Public Type Definitions
3233
****************************************************************************/
3334

3435
typedef struct
3536
{
36-
mutex_t protected; /* Protecting Locks for Read/Write Locked Tables */
37+
#ifdef CONFIG_SPINLOCK
38+
spinlock_t protected;
39+
#endif
3740
sem_t waiting; /* Reader/writer Waiting queue */
3841
int waiter; /* Waiter Count */
3942
int writer; /* Writer Count */

sched/semaphore/sem_rw.c

+35-25
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@
2323
****************************************************************************/
2424

2525
#include <nuttx/rwsem.h>
26+
#include <nuttx/irq.h>
27+
#include <assert.h>
28+
29+
/****************************************************************************
30+
* Pre-processor Definitions
31+
****************************************************************************/
32+
33+
#undef spin_lock_irqsave
34+
#undef spin_unlock_irqrestore
35+
36+
#if !defined(CONFIG_SPINLOCK) || !defined(CONFIG_SMP)
37+
#define spin_lock_irqsave(lock) up_irq_save()
38+
#define spin_unlock_irqrestore(lock, flags) up_irq_restore(flags)
39+
#endif
2640

2741
/****************************************************************************
2842
* Private Functions
@@ -61,11 +75,11 @@ static inline void up_wait(FAR rw_semaphore_t *rwsem)
6175

6276
int down_read_trylock(FAR rw_semaphore_t *rwsem)
6377
{
64-
nxmutex_lock(&rwsem->protected);
78+
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
6579

6680
if (rwsem->writer > 0)
6781
{
68-
nxmutex_unlock(&rwsem->protected);
82+
spin_unlock_irqrestore(&rwsem->protected, flags);
6983
return 0;
7084
}
7185

@@ -75,7 +89,7 @@ int down_read_trylock(FAR rw_semaphore_t *rwsem)
7589

7690
rwsem->reader++;
7791

78-
nxmutex_unlock(&rwsem->protected);
92+
spin_unlock_irqrestore(&rwsem->protected, flags);
7993

8094
return 1;
8195
}
@@ -97,14 +111,14 @@ void down_read(FAR rw_semaphore_t *rwsem)
97111
* block and wait for the write-lock to be unlocked.
98112
*/
99113

100-
nxmutex_lock(&rwsem->protected);
114+
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
101115

102116
while (rwsem->writer > 0)
103117
{
104118
rwsem->waiter++;
105-
nxmutex_unlock(&rwsem->protected);
119+
spin_unlock_irqrestore(&rwsem->protected, flags);
106120
nxsem_wait(&rwsem->waiting);
107-
nxmutex_lock(&rwsem->protected);
121+
flags = spin_lock_irqsave(&rwsem->protected);
108122
rwsem->waiter--;
109123
}
110124

@@ -114,7 +128,7 @@ void down_read(FAR rw_semaphore_t *rwsem)
114128

115129
rwsem->reader++;
116130

117-
nxmutex_unlock(&rwsem->protected);
131+
spin_unlock_irqrestore(&rwsem->protected, flags);
118132
}
119133

120134
/****************************************************************************
@@ -130,7 +144,7 @@ void down_read(FAR rw_semaphore_t *rwsem)
130144

131145
void up_read(FAR rw_semaphore_t *rwsem)
132146
{
133-
nxmutex_lock(&rwsem->protected);
147+
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
134148

135149
DEBUGASSERT(rwsem->reader > 0);
136150

@@ -141,7 +155,7 @@ void up_read(FAR rw_semaphore_t *rwsem)
141155
up_wait(rwsem);
142156
}
143157

144-
nxmutex_unlock(&rwsem->protected);
158+
spin_unlock_irqrestore(&rwsem->protected, flags);
145159
}
146160

147161
/****************************************************************************
@@ -160,19 +174,19 @@ void up_read(FAR rw_semaphore_t *rwsem)
160174

161175
int down_write_trylock(FAR rw_semaphore_t *rwsem)
162176
{
163-
nxmutex_lock(&rwsem->protected);
177+
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
164178

165179
if (rwsem->writer > 0 || rwsem->reader > 0)
166180
{
167-
nxmutex_unlock(&rwsem->protected);
181+
spin_unlock_irqrestore(&rwsem->protected, flags);
168182
return 0;
169183
}
170184

171185
/* The check passes, then we just need the writer reference + 1 */
172186

173187
rwsem->writer++;
174188

175-
nxmutex_unlock(&rwsem->protected);
189+
spin_unlock_irqrestore(&rwsem->protected, flags);
176190

177191
return 1;
178192
}
@@ -190,22 +204,22 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem)
190204

191205
void down_write(FAR rw_semaphore_t *rwsem)
192206
{
193-
nxmutex_lock(&rwsem->protected);
207+
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
194208

195209
while (rwsem->reader > 0 || rwsem->writer > 0)
196210
{
197211
rwsem->waiter++;
198-
nxmutex_unlock(&rwsem->protected);
212+
spin_unlock_irqrestore(&rwsem->protected, flags);
199213
nxsem_wait(&rwsem->waiting);
200-
nxmutex_lock(&rwsem->protected);
214+
flags = spin_lock_irqsave(&rwsem->protected);
201215
rwsem->waiter--;
202216
}
203217

204218
/* The check passes, then we just need the writer reference + 1 */
205219

206220
rwsem->writer++;
207221

208-
nxmutex_unlock(&rwsem->protected);
222+
spin_unlock_irqrestore(&rwsem->protected, flags);
209223
}
210224

211225
/****************************************************************************
@@ -221,15 +235,15 @@ void down_write(FAR rw_semaphore_t *rwsem)
221235

222236
void up_write(FAR rw_semaphore_t *rwsem)
223237
{
224-
nxmutex_lock(&rwsem->protected);
238+
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
225239

226240
DEBUGASSERT(rwsem->writer > 0);
227241

228242
rwsem->writer--;
229243

230244
up_wait(rwsem);
231245

232-
nxmutex_unlock(&rwsem->protected);
246+
spin_unlock_irqrestore(&rwsem->protected, flags);
233247
}
234248

235249
/****************************************************************************
@@ -253,16 +267,13 @@ int init_rwsem(FAR rw_semaphore_t *rwsem)
253267

254268
/* Initialize structure information */
255269

256-
ret = nxmutex_init(&rwsem->protected);
257-
if (ret < 0)
258-
{
259-
return ret;
260-
}
270+
#ifdef CONFIG_SPINLOCK
271+
spin_lock_init(&rwsem->protected);
272+
#endif
261273

262274
ret = nxsem_init(&rwsem->waiting, 0, 0);
263275
if (ret < 0)
264276
{
265-
nxmutex_destroy(&rwsem->protected);
266277
return ret;
267278
}
268279

@@ -292,6 +303,5 @@ void destroy_rwsem(FAR rw_semaphore_t *rwsem)
292303
DEBUGASSERT(rwsem->waiter == 0 && rwsem->reader == 0 &&
293304
rwsem->writer == 0);
294305

295-
nxmutex_destroy(&rwsem->protected);
296306
nxsem_destroy(&rwsem->waiting);
297307
}

0 commit comments

Comments
 (0)