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 <keithp@keithp.com>
This commit is contained in:
parent
96f51bf797
commit
f075022bec
@ -7,8 +7,18 @@
|
||||
#include "picolibc-hooks.h"
|
||||
|
||||
#ifdef CONFIG_MULTITHREADING
|
||||
#define _LOCK_T void *
|
||||
K_MUTEX_DEFINE(__lock___libc_recursive_mutex);
|
||||
|
||||
#include <sys/lock.h>
|
||||
|
||||
/* Define the picolibc lock type */
|
||||
struct __lock {
|
||||
struct k_mutex m;
|
||||
};
|
||||
|
||||
STRUCT_SECTION_ITERABLE_ALTERNATE(k_mutex, __lock,
|
||||
__lock___libc_recursive_mutex) = {
|
||||
.m = Z_MUTEX_INITIALIZER(__lock___libc_recursive_mutex.m),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/* Grant public access to picolibc lock after boot */
|
||||
@ -32,13 +42,13 @@ void __retarget_lock_init_recursive(_LOCK_T *lock)
|
||||
|
||||
/* Allocate mutex object */
|
||||
#ifndef CONFIG_USERSPACE
|
||||
*lock = malloc(sizeof(struct k_mutex));
|
||||
*lock = malloc(sizeof(struct __lock));
|
||||
#else
|
||||
*lock = k_object_alloc(K_OBJ_MUTEX);
|
||||
#endif /* !CONFIG_USERSPACE */
|
||||
__ASSERT(*lock != NULL, "recursive lock allocation failed");
|
||||
|
||||
k_mutex_init((struct k_mutex *)*lock);
|
||||
k_mutex_init(&(*lock)->m);
|
||||
}
|
||||
|
||||
/* Create a new dynamic non-recursive lock */
|
||||
@ -68,7 +78,7 @@ void __retarget_lock_close(_LOCK_T lock)
|
||||
void __retarget_lock_acquire_recursive(_LOCK_T lock)
|
||||
{
|
||||
__ASSERT_NO_MSG(lock != NULL);
|
||||
k_mutex_lock((struct k_mutex *)lock, K_FOREVER);
|
||||
k_mutex_lock(&lock->m, K_FOREVER);
|
||||
}
|
||||
|
||||
/* Acquiure non-recursive lock */
|
||||
@ -81,7 +91,7 @@ void __retarget_lock_acquire(_LOCK_T lock)
|
||||
int __retarget_lock_try_acquire_recursive(_LOCK_T lock)
|
||||
{
|
||||
__ASSERT_NO_MSG(lock != NULL);
|
||||
return !k_mutex_lock((struct k_mutex *)lock, K_NO_WAIT);
|
||||
return !k_mutex_lock(&lock->m, K_NO_WAIT);
|
||||
}
|
||||
|
||||
/* Try acquiring non-recursive lock */
|
||||
@ -94,7 +104,7 @@ int __retarget_lock_try_acquire(_LOCK_T lock)
|
||||
void __retarget_lock_release_recursive(_LOCK_T lock)
|
||||
{
|
||||
__ASSERT_NO_MSG(lock != NULL);
|
||||
k_mutex_unlock((struct k_mutex *)lock);
|
||||
k_mutex_unlock(&lock->m);
|
||||
}
|
||||
|
||||
/* Release non-recursive lock */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user