Skip to content

Commit f075022

Browse files
keith-packardkartben
authored andcommitted
libc/picolibc: Make lock typing match between Zephyr and picolibc
Picolibc's retargetable locking is based upon having the user own the lock type (struct __lock, along with typedef struct __lock *_LOCK_T), and then having the picolibc internal code only refer to this type via the _LOCK_T pointer typedef, leaving the actual struct undeclared there. Zephyr wants to use 'struct k_mutex' for this type; the initial picolibc port handled this by trying to redefine the picolibc locking to use 'void *' instead of 'struct __lock *' by including '#define _LOCK_T void *'. Which 'works' as long as the Zephyr code doesn't actually include picolibc's sys/lock.h. A recent picolibc change to support POSIX stdio locking has picolibc's stdio.h including sys/lock.h, which breaks Zephyr's hack. To fix this, create a real 'struct __lock' type as struct __lock { struct k_mutex m; }; Define all of the required picolibc locking API with this real type, referring to the mutex inside without needing any casts. This required switching the definition of the C library global lock from K_MUTEX_DEFINE to the open-coded version, STRUCT_SECTION_ITERABLE_ALTERNATE so that it has the correct type and still lands in the same elf section. The only mildly inappropriate code left is that lock are allocated using k_object_alloc(K_OBJ_MUTEX), which "works" because the size of 'struct __lock` will exactly match the size of 'struct k_mutex' because of C's struct allocation rules. Signed-off-by: Keith Packard <[email protected]>
1 parent 96f51bf commit f075022

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

lib/libc/picolibc/locks.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,18 @@
77
#include "picolibc-hooks.h"
88

99
#ifdef CONFIG_MULTITHREADING
10-
#define _LOCK_T void *
11-
K_MUTEX_DEFINE(__lock___libc_recursive_mutex);
10+
11+
#include <sys/lock.h>
12+
13+
/* Define the picolibc lock type */
14+
struct __lock {
15+
struct k_mutex m;
16+
};
17+
18+
STRUCT_SECTION_ITERABLE_ALTERNATE(k_mutex, __lock,
19+
__lock___libc_recursive_mutex) = {
20+
.m = Z_MUTEX_INITIALIZER(__lock___libc_recursive_mutex.m),
21+
};
1222

1323
#ifdef CONFIG_USERSPACE
1424
/* Grant public access to picolibc lock after boot */
@@ -32,13 +42,13 @@ void __retarget_lock_init_recursive(_LOCK_T *lock)
3242

3343
/* Allocate mutex object */
3444
#ifndef CONFIG_USERSPACE
35-
*lock = malloc(sizeof(struct k_mutex));
45+
*lock = malloc(sizeof(struct __lock));
3646
#else
3747
*lock = k_object_alloc(K_OBJ_MUTEX);
3848
#endif /* !CONFIG_USERSPACE */
3949
__ASSERT(*lock != NULL, "recursive lock allocation failed");
4050

41-
k_mutex_init((struct k_mutex *)*lock);
51+
k_mutex_init(&(*lock)->m);
4252
}
4353

4454
/* Create a new dynamic non-recursive lock */
@@ -68,7 +78,7 @@ void __retarget_lock_close(_LOCK_T lock)
6878
void __retarget_lock_acquire_recursive(_LOCK_T lock)
6979
{
7080
__ASSERT_NO_MSG(lock != NULL);
71-
k_mutex_lock((struct k_mutex *)lock, K_FOREVER);
81+
k_mutex_lock(&lock->m, K_FOREVER);
7282
}
7383

7484
/* Acquiure non-recursive lock */
@@ -81,7 +91,7 @@ void __retarget_lock_acquire(_LOCK_T lock)
8191
int __retarget_lock_try_acquire_recursive(_LOCK_T lock)
8292
{
8393
__ASSERT_NO_MSG(lock != NULL);
84-
return !k_mutex_lock((struct k_mutex *)lock, K_NO_WAIT);
94+
return !k_mutex_lock(&lock->m, K_NO_WAIT);
8595
}
8696

8797
/* Try acquiring non-recursive lock */
@@ -94,7 +104,7 @@ int __retarget_lock_try_acquire(_LOCK_T lock)
94104
void __retarget_lock_release_recursive(_LOCK_T lock)
95105
{
96106
__ASSERT_NO_MSG(lock != NULL);
97-
k_mutex_unlock((struct k_mutex *)lock);
107+
k_mutex_unlock(&lock->m);
98108
}
99109

100110
/* Release non-recursive lock */

0 commit comments

Comments
 (0)