diff --git a/include/kernel.h b/include/kernel.h index e3c55b10d70..cbdb1da130a 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -2477,8 +2477,13 @@ struct k_sem { * * @return N/A */ -extern void k_sem_init(struct k_sem *sem, unsigned int initial_count, - unsigned int limit); +static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count, + unsigned int limit); + +K_SYSCALL_DECLARE3_VOID(K_SYSCALL_SEM_INIT, k_sem_init, + struct k_sem *, sem, + unsigned int, initial_count, + unsigned int, limit); /** * @brief Take a semaphore. @@ -2501,7 +2506,11 @@ extern void k_sem_init(struct k_sem *sem, unsigned int initial_count, * @retval -EBUSY Returned without waiting. * @retval -EAGAIN Waiting period timed out. */ -extern int k_sem_take(struct k_sem *sem, s32_t timeout); +static inline int k_sem_take(struct k_sem *sem, s32_t timeout); + +K_SYSCALL_DECLARE2(K_SYSCALL_SEM_TAKE, k_sem_take, int, + struct k_sem *, sem, + s32_t, timeout); /** * @brief Give a semaphore. @@ -2515,7 +2524,10 @@ extern int k_sem_take(struct k_sem *sem, s32_t timeout); * * @return N/A */ -extern void k_sem_give(struct k_sem *sem); +static inline void k_sem_give(struct k_sem *sem); + +K_SYSCALL_DECLARE1_VOID(K_SYSCALL_SEM_GIVE, k_sem_give, + struct k_sem *, sem); /** * @brief Reset a semaphore's count to zero. @@ -2526,11 +2538,16 @@ extern void k_sem_give(struct k_sem *sem); * * @return N/A */ -static inline void k_sem_reset(struct k_sem *sem) +static inline void k_sem_reset(struct k_sem *sem); + +static inline void _impl_k_sem_reset(struct k_sem *sem) { sem->count = 0; } +K_SYSCALL_DECLARE1_VOID_INLINE(K_SYSCALL_SEM_RESET, k_sem_reset, + struct k_sem *, sem); + /** * @brief Get a semaphore's count. * @@ -2540,11 +2557,16 @@ static inline void k_sem_reset(struct k_sem *sem) * * @return Current semaphore count. */ -static inline unsigned int k_sem_count_get(struct k_sem *sem) +static inline unsigned int k_sem_count_get(struct k_sem *sem); + +static inline unsigned int _impl_k_sem_count_get(struct k_sem *sem) { return sem->count; } +K_SYSCALL_DECLARE1_INLINE(K_SYSCALL_SEM_COUNT_GET, k_sem_count_get, + unsigned int, struct k_sem *, sem); + /** * @brief Statically define and initialize a semaphore. * diff --git a/include/syscall_list.h b/include/syscall_list.h index 5ce17b1fd39..8798d131f51 100644 --- a/include/syscall_list.h +++ b/include/syscall_list.h @@ -12,6 +12,11 @@ enum { K_SYSCALL_BAD, + K_SYSCALL_SEM_INIT, + K_SYSCALL_SEM_GIVE, + K_SYSCALL_SEM_TAKE, + K_SYSCALL_SEM_RESET, + K_SYSCALL_SEM_COUNT_GET, K_SYSCALL_LIMIT /* Always last */ }; diff --git a/kernel/sem.c b/kernel/sem.c index 4970113e52c..51b4819bcf6 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -25,6 +25,7 @@ #include #include #include +#include extern struct k_sem _k_sem_list_start[]; extern struct k_sem _k_sem_list_end[]; @@ -52,8 +53,8 @@ SYS_INIT(init_sem_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); #endif /* CONFIG_OBJECT_TRACING */ -void k_sem_init(struct k_sem *sem, unsigned int initial_count, - unsigned int limit) +void _impl_k_sem_init(struct k_sem *sem, unsigned int initial_count, + unsigned int limit) { __ASSERT(limit != 0, "limit cannot be zero"); @@ -69,6 +70,18 @@ void k_sem_init(struct k_sem *sem, unsigned int initial_count, _k_object_init(sem); } +#ifdef CONFIG_USERSPACE +u32_t _handler_k_sem_init(u32_t sem_ptr, u32_t initial_count, u32_t limit, + u32_t arg4, u32_t arg5, u32_t arg6, void *ssf) +{ + _SYSCALL_ARG3; + + _SYSCALL_IS_OBJ(sem_ptr, K_OBJ_SEM, 1, ssf); + _SYSCALL_VERIFY(limit != 0, ssf); + _impl_k_sem_init((struct k_sem *)sem_ptr, initial_count, limit); + return 0; +} +#endif /* returns 1 if a reschedule must take place, 0 otherwise */ static inline int handle_poll_events(struct k_sem *sem) @@ -129,7 +142,7 @@ void _sem_give_non_preemptible(struct k_sem *sem) _set_thread_return_value(thread, 0); } -void k_sem_give(struct k_sem *sem) +void _impl_k_sem_give(struct k_sem *sem) { unsigned int key; @@ -142,7 +155,20 @@ void k_sem_give(struct k_sem *sem) } } -int k_sem_take(struct k_sem *sem, s32_t timeout) +#ifdef CONFIG_USERSPACE +u32_t _handler_k_sem_give(u32_t sem_ptr, u32_t arg2, u32_t arg3, + u32_t arg4, u32_t arg5, u32_t arg6, void *ssf) +{ + _SYSCALL_ARG1; + + _SYSCALL_IS_OBJ(sem_ptr, K_OBJ_SEM, 0, ssf); + _impl_k_sem_give((struct k_sem *)sem_ptr); + + return 0; +} +#endif /* CONFIG_USERSPACE */ + +int _impl_k_sem_take(struct k_sem *sem, s32_t timeout) { __ASSERT(!_is_in_isr() || timeout == K_NO_WAIT, ""); @@ -163,3 +189,36 @@ int k_sem_take(struct k_sem *sem, s32_t timeout) return _Swap(key); } + +#ifdef CONFIG_USERSPACE +u32_t _handler_k_sem_take(u32_t sem_ptr, u32_t timeout, u32_t arg3, + u32_t arg4, u32_t arg5, u32_t arg6, void *ssf) +{ + _SYSCALL_ARG2; + + _SYSCALL_IS_OBJ(sem_ptr, K_OBJ_SEM, 0, ssf); + _impl_k_sem_take((struct k_sem *)sem_ptr, timeout); + + return 0; +} + +u32_t _handler_k_sem_reset(u32_t sem_ptr, u32_t arg2, u32_t arg3, + u32_t arg4, u32_t arg5, u32_t arg6, void *ssf) +{ + _SYSCALL_ARG1; + + _SYSCALL_IS_OBJ(sem_ptr, K_OBJ_SEM, 0, ssf); + _impl_k_sem_reset((struct k_sem *)sem_ptr); + + return 0; +} + +u32_t _handler_k_sem_count_get(u32_t sem_ptr, u32_t arg2, u32_t arg3, + u32_t arg4, u32_t arg5, u32_t arg6, void *ssf) +{ + _SYSCALL_ARG1; + + _SYSCALL_IS_OBJ(sem_ptr, K_OBJ_SEM, 0, ssf); + return _impl_k_sem_count_get((struct k_sem *)sem_ptr); +} +#endif /* CONFIG_USERSPACE */ diff --git a/kernel/userspace.c b/kernel/userspace.c index f540fd924a5..ac2a6fb797c 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -192,4 +192,10 @@ static u32_t _handler_bad_syscall(u32_t bad_id, u32_t arg2, u32_t arg3, const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = { [K_SYSCALL_BAD] = _handler_bad_syscall, + + [K_SYSCALL_SEM_INIT] = _handler_k_sem_init, + [K_SYSCALL_SEM_GIVE] = _handler_k_sem_give, + [K_SYSCALL_SEM_TAKE] = _handler_k_sem_take, + [K_SYSCALL_SEM_RESET] = _handler_k_sem_reset, + [K_SYSCALL_SEM_COUNT_GET] = _handler_k_sem_count_get, };