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 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 }; 22 23 #ifdef CONFIG_USERSPACE 24 /* Grant public access to picolibc lock after boot */ picolibc_locks_prepare(void)25static int picolibc_locks_prepare(void) 26 { 27 28 /* Initialise recursive locks */ 29 k_object_access_all_grant(&__lock___libc_recursive_mutex); 30 31 return 0; 32 } 33 34 SYS_INIT(picolibc_locks_prepare, POST_KERNEL, 35 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); 36 #endif /* CONFIG_USERSPACE */ 37 38 /* Create a new dynamic recursive lock */ __retarget_lock_init_recursive(_LOCK_T * lock)39void __retarget_lock_init_recursive(_LOCK_T *lock) 40 { 41 __ASSERT_NO_MSG(lock != NULL); 42 43 /* Allocate mutex object */ 44 #ifndef CONFIG_USERSPACE 45 *lock = malloc(sizeof(struct __lock)); 46 #else 47 *lock = k_object_alloc(K_OBJ_MUTEX); 48 #endif /* !CONFIG_USERSPACE */ 49 __ASSERT(*lock != NULL, "recursive lock allocation failed"); 50 51 k_mutex_init(&(*lock)->m); 52 } 53 54 /* Create a new dynamic non-recursive lock */ __retarget_lock_init(_LOCK_T * lock)55void __retarget_lock_init(_LOCK_T *lock) 56 { 57 __retarget_lock_init_recursive(lock); 58 } 59 60 /* Close dynamic recursive lock */ __retarget_lock_close_recursive(_LOCK_T lock)61void __retarget_lock_close_recursive(_LOCK_T lock) 62 { 63 __ASSERT_NO_MSG(lock != NULL); 64 #ifndef CONFIG_USERSPACE 65 free(lock); 66 #else 67 k_object_release(lock); 68 #endif /* !CONFIG_USERSPACE */ 69 } 70 71 /* Close dynamic non-recursive lock */ __retarget_lock_close(_LOCK_T lock)72void __retarget_lock_close(_LOCK_T lock) 73 { 74 __retarget_lock_close_recursive(lock); 75 } 76 77 /* Acquiure recursive lock */ __retarget_lock_acquire_recursive(_LOCK_T lock)78void __retarget_lock_acquire_recursive(_LOCK_T lock) 79 { 80 __ASSERT_NO_MSG(lock != NULL); 81 k_mutex_lock(&lock->m, K_FOREVER); 82 } 83 84 /* Acquiure non-recursive lock */ __retarget_lock_acquire(_LOCK_T lock)85void __retarget_lock_acquire(_LOCK_T lock) 86 { 87 __retarget_lock_acquire_recursive(lock); 88 } 89 90 /* Try acquiring recursive lock */ __retarget_lock_try_acquire_recursive(_LOCK_T lock)91int __retarget_lock_try_acquire_recursive(_LOCK_T lock) 92 { 93 __ASSERT_NO_MSG(lock != NULL); 94 return !k_mutex_lock(&lock->m, K_NO_WAIT); 95 } 96 97 /* Try acquiring non-recursive lock */ __retarget_lock_try_acquire(_LOCK_T lock)98int __retarget_lock_try_acquire(_LOCK_T lock) 99 { 100 return __retarget_lock_try_acquire_recursive(lock); 101 } 102 103 /* Release recursive lock */ __retarget_lock_release_recursive(_LOCK_T lock)104void __retarget_lock_release_recursive(_LOCK_T lock) 105 { 106 __ASSERT_NO_MSG(lock != NULL); 107 k_mutex_unlock(&lock->m); 108 } 109 110 /* Release non-recursive lock */ __retarget_lock_release(_LOCK_T lock)111void __retarget_lock_release(_LOCK_T lock) 112 { 113 __retarget_lock_release_recursive(lock); 114 } 115 116 #endif /* CONFIG_MULTITHREADING */ 117