Skip to content

Commit 5a5c54c

Browse files
crafcat7xiaoxiang781216
authored andcommitted
lib_pathbuffer.c:Use atomic instead of locks
Summary: Use atomic_cmpxchg to ensure that in multithreaded situations, if someone releases the buffer, it can be applied for in time. And use atomic_ulong to save free_bitmap Signed-off-by: chenrun1 <[email protected]>
1 parent 60bf682 commit 5a5c54c

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

libs/libc/misc/lib_pathbuffer.c

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
****************************************************************************/
2626

2727
#include <nuttx/config.h>
28-
#include <nuttx/spinlock.h>
28+
#include <nuttx/atomic.h>
2929
#include <nuttx/lib/lib.h>
3030

3131
#include <stdlib.h>
@@ -41,8 +41,7 @@
4141

4242
struct pathbuffer_s
4343
{
44-
spinlock_t lock; /* Lock for the buffer */
45-
unsigned long free_bitmap; /* Bitmap of free buffer */
44+
atomic_t free_bitmap; /* Bitmap of free buffer */
4645
char buffer[CONFIG_LIBC_PATHBUFFER_MAX][PATH_MAX];
4746
};
4847

@@ -52,7 +51,6 @@ struct pathbuffer_s
5251

5352
static struct pathbuffer_s g_pathbuffer =
5453
{
55-
SP_UNLOCKED,
5654
(1u << CONFIG_LIBC_PATHBUFFER_MAX) - 1,
5755
};
5856

@@ -82,22 +80,24 @@ static struct pathbuffer_s g_pathbuffer =
8280

8381
FAR char *lib_get_pathbuffer(void)
8482
{
85-
irqstate_t flags;
86-
int index;
87-
88-
/* Try to find a free buffer */
89-
90-
flags = spin_lock_irqsave(&g_pathbuffer.lock);
91-
index = ffsl(g_pathbuffer.free_bitmap) - 1;
92-
if (index >= 0 && index < CONFIG_LIBC_PATHBUFFER_MAX)
83+
for (; ; )
9384
{
94-
g_pathbuffer.free_bitmap &= ~(1u << index);
95-
spin_unlock_irqrestore(&g_pathbuffer.lock, flags);
96-
return g_pathbuffer.buffer[index];
85+
int32_t update;
86+
int32_t free_bitmap = atomic_read(&g_pathbuffer.free_bitmap);
87+
int index = ffsl(free_bitmap) - 1;
88+
if (index < 0 || index >= CONFIG_LIBC_PATHBUFFER_MAX)
89+
{
90+
break;
91+
}
92+
93+
update = free_bitmap & ~(1u << index);
94+
if (atomic_cmpxchg(&g_pathbuffer.free_bitmap, &free_bitmap,
95+
update))
96+
{
97+
return g_pathbuffer.buffer[index];
98+
}
9799
}
98100

99-
spin_unlock_irqrestore(&g_pathbuffer.lock, flags);
100-
101101
/* If no free buffer is found, allocate a new one if
102102
* CONFIG_LIBC_PATHBUFFER_MALLOC is enabled
103103
*/
@@ -125,17 +125,12 @@ FAR char *lib_get_pathbuffer(void)
125125

126126
void lib_put_pathbuffer(FAR char *buffer)
127127
{
128-
irqstate_t flags;
129-
int index;
130-
131-
index = (buffer - &g_pathbuffer.buffer[0][0]) / PATH_MAX;
128+
int index = (buffer - &g_pathbuffer.buffer[0][0]) / PATH_MAX;
132129
if (index >= 0 && index < CONFIG_LIBC_PATHBUFFER_MAX)
133130
{
134-
/* Mark the corresponding bit as free */
135-
136-
flags = spin_lock_irqsave(&g_pathbuffer.lock);
137-
g_pathbuffer.free_bitmap |= 1u << index;
138-
spin_unlock_irqrestore(&g_pathbuffer.lock, flags);
131+
DEBUGASSERT((atomic_read(&g_pathbuffer.free_bitmap) &
132+
(1u << index)) == 0);
133+
atomic_fetch_or_acquire(&g_pathbuffer.free_bitmap, 1u << index);
139134
return;
140135
}
141136

0 commit comments

Comments
 (0)