1 /* 2 * Copyright © 2021, Keith Packard <keithp@keithp.com> 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include "picolibc-hooks.h" 8 9 #ifdef CONFIG_MULTITHREADING 10 #define _LOCK_T void * 11 K_MUTEX_DEFINE(__lock___libc_recursive_mutex); 12 13 #ifdef CONFIG_USERSPACE 14 /* Grant public access to picolibc lock after boot */ picolibc_locks_prepare(void)15static int picolibc_locks_prepare(void) 16 { 17 18 /* Initialise recursive locks */ 19 k_object_access_all_grant(&__lock___libc_recursive_mutex); 20 21 return 0; 22 } 23 24 SYS_INIT(picolibc_locks_prepare, POST_KERNEL, 25 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); 26 #endif /* CONFIG_USERSPACE */ 27 28 /* Create a new dynamic recursive lock */ __retarget_lock_init_recursive(_LOCK_T * lock)29void __retarget_lock_init_recursive(_LOCK_T *lock) 30 { 31 __ASSERT_NO_MSG(lock != NULL); 32 33 /* Allocate mutex object */ 34 #ifndef CONFIG_USERSPACE 35 *lock = malloc(sizeof(struct k_mutex)); 36 #else 37 *lock = k_object_alloc(K_OBJ_MUTEX); 38 #endif /* !CONFIG_USERSPACE */ 39 __ASSERT(*lock != NULL, "recursive lock allocation failed"); 40 41 k_mutex_init((struct k_mutex *)*lock); 42 } 43 44 /* Create a new dynamic non-recursive lock */ __retarget_lock_init(_LOCK_T * lock)45void __retarget_lock_init(_LOCK_T *lock) 46 { 47 __retarget_lock_init_recursive(lock); 48 } 49 50 /* Close dynamic recursive lock */ __retarget_lock_close_recursive(_LOCK_T lock)51void __retarget_lock_close_recursive(_LOCK_T lock) 52 { 53 __ASSERT_NO_MSG(lock != NULL); 54 #ifndef CONFIG_USERSPACE 55 free(lock); 56 #else 57 k_object_release(lock); 58 #endif /* !CONFIG_USERSPACE */ 59 } 60 61 /* Close dynamic non-recursive lock */ __retarget_lock_close(_LOCK_T lock)62void __retarget_lock_close(_LOCK_T lock) 63 { 64 __retarget_lock_close_recursive(lock); 65 } 66 67 /* Acquiure recursive lock */ __retarget_lock_acquire_recursive(_LOCK_T lock)68void __retarget_lock_acquire_recursive(_LOCK_T lock) 69 { 70 __ASSERT_NO_MSG(lock != NULL); 71 k_mutex_lock((struct k_mutex *)lock, K_FOREVER); 72 } 73 74 /* Acquiure non-recursive lock */ __retarget_lock_acquire(_LOCK_T lock)75void __retarget_lock_acquire(_LOCK_T lock) 76 { 77 __retarget_lock_acquire_recursive(lock); 78 } 79 80 /* Try acquiring recursive lock */ __retarget_lock_try_acquire_recursive(_LOCK_T lock)81int __retarget_lock_try_acquire_recursive(_LOCK_T lock) 82 { 83 __ASSERT_NO_MSG(lock != NULL); 84 return !k_mutex_lock((struct k_mutex *)lock, K_NO_WAIT); 85 } 86 87 /* Try acquiring non-recursive lock */ __retarget_lock_try_acquire(_LOCK_T lock)88int __retarget_lock_try_acquire(_LOCK_T lock) 89 { 90 return __retarget_lock_try_acquire_recursive(lock); 91 } 92 93 /* Release recursive lock */ __retarget_lock_release_recursive(_LOCK_T lock)94void __retarget_lock_release_recursive(_LOCK_T lock) 95 { 96 __ASSERT_NO_MSG(lock != NULL); 97 k_mutex_unlock((struct k_mutex *)lock); 98 } 99 100 /* Release non-recursive lock */ __retarget_lock_release(_LOCK_T lock)101void __retarget_lock_release(_LOCK_T lock) 102 { 103 __retarget_lock_release_recursive(lock); 104 } 105 106 #endif /* CONFIG_MULTITHREADING */ 107