f0835674a3
For systems without userspace enabled, these work the same as a k_mutex. For systems with userspace, the sys_mutex may exist in user memory. It is still tracked as a kernel object, but has an underlying k_mutex that is looked up in the kernel object table. Future enhancements will optimize sys_mutex to not require syscalls for uncontended sys_mutexes, using atomic ops instead. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
79 lines
1.6 KiB
C
79 lines
1.6 KiB
C
/*
|
|
* Copyright (c) 2019 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <misc/mutex.h>
|
|
#include <syscall_handler.h>
|
|
#include <kernel_structs.h>
|
|
|
|
static struct k_mutex *get_k_mutex(struct sys_mutex *mutex)
|
|
{
|
|
struct _k_object *obj;
|
|
|
|
obj = z_object_find(mutex);
|
|
if (obj == NULL || obj->type != K_OBJ_SYS_MUTEX) {
|
|
return NULL;
|
|
}
|
|
|
|
return (struct k_mutex *)obj->data;
|
|
}
|
|
|
|
static bool check_sys_mutex_addr(u32_t addr)
|
|
{
|
|
/* sys_mutex memory is never touched, just used to lookup the
|
|
* underlying k_mutex, but we don't want threads using mutexes
|
|
* that are outside their memory domain
|
|
*/
|
|
return Z_SYSCALL_MEMORY_WRITE(addr, sizeof(struct sys_mutex));
|
|
}
|
|
|
|
int z_impl_z_sys_mutex_kernel_lock(struct sys_mutex *mutex, s32_t timeout)
|
|
{
|
|
struct k_mutex *kernel_mutex = get_k_mutex(mutex);
|
|
|
|
if (kernel_mutex == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return k_mutex_lock(kernel_mutex, timeout);
|
|
}
|
|
|
|
Z_SYSCALL_HANDLER(z_sys_mutex_kernel_lock, mutex, timeout)
|
|
{
|
|
if (check_sys_mutex_addr(mutex)) {
|
|
return -EACCES;
|
|
}
|
|
|
|
return z_impl_z_sys_mutex_kernel_lock((struct sys_mutex *)mutex,
|
|
timeout);
|
|
}
|
|
|
|
int z_impl_z_sys_mutex_kernel_unlock(struct sys_mutex *mutex)
|
|
{
|
|
struct k_mutex *kernel_mutex = get_k_mutex(mutex);
|
|
|
|
if (kernel_mutex == NULL || kernel_mutex->lock_count == 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (kernel_mutex->owner != _current) {
|
|
return -EPERM;
|
|
}
|
|
|
|
k_mutex_unlock(kernel_mutex);
|
|
return 0;
|
|
}
|
|
|
|
Z_SYSCALL_HANDLER(z_sys_mutex_kernel_unlock, mutex)
|
|
{
|
|
if (check_sys_mutex_addr(mutex)) {
|
|
return -EACCES;
|
|
}
|
|
|
|
return z_impl_z_sys_mutex_kernel_unlock((struct sys_mutex *)mutex);
|
|
}
|
|
|