feat(kmutex): Added kernel mutex.
This commit is contained in:
@@ -5,7 +5,7 @@ menu "OS options"
|
||||
default n
|
||||
help
|
||||
This option controls whether to use kernel os.
|
||||
|
||||
# KTHREAD
|
||||
config MR_CFG_KTHREAD_ITHREAD_SIZE
|
||||
depends on MR_USE_KOS
|
||||
int "Kthread inline thread size"
|
||||
@@ -13,4 +13,18 @@ menu "OS options"
|
||||
range 4 1024
|
||||
help
|
||||
This option controls the size of the inline thread of the kthread.
|
||||
# KMUTEX
|
||||
config MR_USE_KMUTEX
|
||||
depends on MR_USE_KOS
|
||||
bool "Use kernel mutex"
|
||||
default n
|
||||
help
|
||||
This option controls whether to use kernel mutex.
|
||||
config MR_CFG_KTHREAD_ITHREAD_SIZE
|
||||
depends on MR_USE_KMUTEX
|
||||
int "Kmutex inline mutex size"
|
||||
default 64
|
||||
range 4 1024
|
||||
help
|
||||
This option controls the size of the inline mutex of the kmutex.
|
||||
endmenu
|
||||
|
||||
133
include/kernel/os/mr_kmutex.h
Normal file
133
include/kernel/os/mr_kmutex.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KMUTEX_H__
|
||||
#define __MR_KMUTEX_H__
|
||||
|
||||
#include <mr_config.h>
|
||||
#if defined(MR_USE_KOS) && defined(MR_USE_KMUTEX)
|
||||
#include <kernel/mr_kclock.h>
|
||||
#include <kernel/mr_kobject.h>
|
||||
#endif /* defined(MR_USE_KOS) && defined(MR_USE_KMUTEX) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kmutex
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(MR_USE_KOS) && defined(MR_USE_KMUTEX)
|
||||
/* Kmutex type */
|
||||
typedef struct mr_kmutex {
|
||||
struct mr_kobject parent;
|
||||
mr_ptr_t mutex;
|
||||
#if !defined(MR_CFG_KMUTEX_IMUTEX_SIZE)
|
||||
#define MR_CFG_KMUTEX_IMUTEX_SIZE (64)
|
||||
#endif /* !defined(MR_CFG_KMUTEX_IMUTEX_SIZE) */
|
||||
mr_uint8_t imutex[MR_CFG_KMUTEX_IMUTEX_SIZE];
|
||||
} mr_kmutex_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function checks if a kmutex is initialized.
|
||||
*
|
||||
* @param _kmutex The kmutex.
|
||||
* @return MR_TRUE if the kmutex is initialized, MR_FALSE otherwise.
|
||||
*/
|
||||
#define MR_KMUTEX_IS_INITED(_kmutex) MR_KOBJECT_IS_INITED(_kmutex)
|
||||
|
||||
/**
|
||||
* @brief This function initializes a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
* @param name The kmutex name.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmutex_init(mr_kmutex_t *kmutex, const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function create a kmutex.
|
||||
*
|
||||
* @param name The kmutex name.
|
||||
* @return The kmutex on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_kmutex_t *mr_kmutex_create(const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function delete a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmutex_del(mr_kmutex_t *kmutex);
|
||||
|
||||
/**
|
||||
* @brief This function take a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
* @param timeout The timeout(tick).
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note If timeout is '0', no waiting.
|
||||
* @note If timeout is '-1', waiting forever.
|
||||
*/
|
||||
mr_err_t mr_kmutex_take(mr_kmutex_t *kmutex, mr_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief This function try to take a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmutex_trytake(mr_kmutex_t *kmutex);
|
||||
|
||||
/**
|
||||
* @brief This function give a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmutex_give(mr_kmutex_t *kmutex);
|
||||
|
||||
/**
|
||||
* @brief This function find a kmutex.
|
||||
*
|
||||
* @param name The kmutex name.
|
||||
* @return The kmutex on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_kmutex_t *mr_kmutex_find(const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function get a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
* @return The kmutex on success, or MR_NULL on failure.
|
||||
*/
|
||||
MR_INLINE mr_kmutex_t *mr_kmutex_get(mr_kmutex_t *kmutex) {
|
||||
return (mr_kmutex_t *)mr_kobject_get((mr_kobject_t *)kmutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function put a kmutex.
|
||||
*
|
||||
* @param kmutex The kmutex.
|
||||
*/
|
||||
MR_INLINE void mr_kmutex_put(mr_kmutex_t *kmutex) {
|
||||
mr_kobject_put((mr_kobject_t *)kmutex);
|
||||
}
|
||||
#endif /* defined(MR_USE_KOS) && defined(MR_USE_KMUTEX) */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KMUTEX_H__ */
|
||||
71
include/port/mr_port_mutex.h
Normal file
71
include/port/mr_port_mutex.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_PORT_MUTEX_H__
|
||||
#define __MR_PORT_MUTEX_H__
|
||||
|
||||
#include <kernel/mr_kclock.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Port-mutex
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function initializes a mutex.
|
||||
*
|
||||
* @param mutex The mutex to be initialized.
|
||||
* @param name The mutex name.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note User implementation.
|
||||
*/
|
||||
extern mr_err_t mr_port_mutex_init(void *mutex, const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function deletes a mutex.
|
||||
*
|
||||
* @param mutex The mutex to be deleted.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note User implementation.
|
||||
*/
|
||||
extern mr_err_t mr_port_mutex_del(void *mutex);
|
||||
|
||||
/**
|
||||
* @brief This function takes a mutex.
|
||||
*
|
||||
* @param mutex The mutex to be taken.
|
||||
* @param timeout The timeout(tick).
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note User implementation.
|
||||
*/
|
||||
extern mr_err_t mr_port_mutex_take(void *mutex, mr_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief This function gives a mutex.
|
||||
*
|
||||
* @param mutex The mutex to be given.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note User implementation.
|
||||
*/
|
||||
extern mr_err_t mr_port_mutex_give(void *mutex);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_PORT_MUTEX_H__ */
|
||||
@@ -91,7 +91,7 @@ extern mr_err_t mr_port_thread_resume(void *thread);
|
||||
*
|
||||
* @note User implementation.
|
||||
*/
|
||||
extern mr_err_t mr_port_thread_yield();
|
||||
extern mr_err_t mr_port_thread_yield(void);
|
||||
|
||||
/**
|
||||
* @brief This function suspends a thread.
|
||||
|
||||
172
kernel/os/kmutex.c
Normal file
172
kernel/os/kmutex.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/os/mr_kmutex.h>
|
||||
#if defined(MR_USE_KOS) && defined(MR_USE_KMUTEX)
|
||||
#include <kernel/mr_initcall.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
#include <port/mr_port_mutex.h>
|
||||
|
||||
/* Kmutex ktype */
|
||||
static mr_ktype_t ktype1, ktype2;
|
||||
/* Kmutex kset */
|
||||
static mr_kset_t kroot = MR_KSET_INIT(&kroot, MR_NULL);
|
||||
|
||||
MR_INLINE mr_err_t kmutex_init(mr_kmutex_t *kmutex, const char *name) {
|
||||
mr_err_t ret;
|
||||
|
||||
/* Init mutex */
|
||||
ret = mr_port_mutex_init(kmutex->imutex, name);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Init kmutex */
|
||||
kmutex->mutex = kmutex->imutex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kmutex_del(mr_kmutex_t *kmutex) {
|
||||
/* Delete mutex */
|
||||
return mr_port_mutex_del(kmutex->mutex);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kmutex_init_add(mr_kmutex_t *kmutex, mr_ktype_t *ktype,
|
||||
const char *name) {
|
||||
mr_err_t ret;
|
||||
|
||||
/* Init kmutex */
|
||||
kmutex_init(kmutex, name);
|
||||
|
||||
/* Init kobject */
|
||||
mr_kobject_init((mr_kobject_t *)kmutex, ktype);
|
||||
|
||||
/* Add kobject to kroot */
|
||||
ret = mr_kobject_add((mr_kobject_t *)kmutex, (mr_kobject_t *)&kroot, name);
|
||||
if (ret != 0) {
|
||||
kmutex_del(kmutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
mr_err_t mr_kmutex_init(mr_kmutex_t *kmutex, const char *name) {
|
||||
/* Check arguments */
|
||||
if ((!kmutex) || MR_KMUTEX_IS_INITED(kmutex) || (!name)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Init and add kmutex */
|
||||
return kmutex_init_add(kmutex, &ktype1, name);
|
||||
}
|
||||
|
||||
mr_kmutex_t *mr_kmutex_create(const char *name) {
|
||||
mr_kmutex_t *kmutex;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if (!name) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Create kmutex */
|
||||
kmutex = mr_malloc(sizeof(mr_kmutex_t));
|
||||
if (!kmutex) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Init and add kmutex */
|
||||
ret = kmutex_init_add(kmutex, &ktype2, name);
|
||||
if (ret != 0) {
|
||||
mr_free(kmutex);
|
||||
return MR_NULL;
|
||||
}
|
||||
return kmutex;
|
||||
}
|
||||
|
||||
mr_err_t mr_kmutex_del(mr_kmutex_t *kmutex) {
|
||||
/* Check arguments */
|
||||
if ((!kmutex) || (!MR_KMUTEX_IS_INITED(kmutex))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete kobject */
|
||||
mr_kobject_del((mr_kobject_t *)kmutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_kmutex_take(mr_kmutex_t *kmutex, mr_tick_t timeout) {
|
||||
/* Check arguments */
|
||||
if ((!kmutex) || (!MR_KMUTEX_IS_INITED(kmutex))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Take mutex */
|
||||
return mr_port_mutex_take(kmutex->mutex, timeout);
|
||||
}
|
||||
|
||||
mr_err_t mr_kmutex_trytake(mr_kmutex_t *kmutex) {
|
||||
/* Check arguments */
|
||||
if ((!kmutex) || (!MR_KMUTEX_IS_INITED(kmutex))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Try take mutex(timeout is '0') */
|
||||
return mr_port_mutex_take(kmutex->mutex, 0);
|
||||
}
|
||||
|
||||
mr_err_t mr_kmutex_give(mr_kmutex_t *kmutex) {
|
||||
/* Check arguments */
|
||||
if ((!kmutex) || (!MR_KMUTEX_IS_INITED(kmutex))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Give mutex */
|
||||
return mr_port_mutex_give(kmutex->mutex);
|
||||
}
|
||||
|
||||
mr_kmutex_t *mr_kmutex_find(const char *name) {
|
||||
/* Lookup kmutex in kroot */
|
||||
return (mr_kmutex_t *)mr_kobject_lookup((mr_kobject_t *)&kroot, name);
|
||||
}
|
||||
|
||||
MR_INLINE mr_kmutex_t *kmutex_release_kobj(mr_kobject_t *kobj) {
|
||||
mr_kmutex_t *kmutex;
|
||||
|
||||
/* Get kmutex */
|
||||
kmutex = MR_CONTAINER_OF(kobj, mr_kmutex_t, parent);
|
||||
|
||||
/* Delete kmutex */
|
||||
kmutex_del(kmutex);
|
||||
return kmutex;
|
||||
}
|
||||
|
||||
MR_INLINE void kmutex_release1_kobj(mr_kobject_t *kobj) {
|
||||
/* Release kmutex */
|
||||
kmutex_release_kobj(kobj);
|
||||
}
|
||||
|
||||
MR_INLINE void kmutex_release2_kobj(mr_kobject_t *kobj) {
|
||||
mr_kmutex_t *kmutex;
|
||||
|
||||
/* Release kmutex */
|
||||
kmutex = kmutex_release_kobj(kobj);
|
||||
|
||||
/* Free kmutex */
|
||||
mr_free(kmutex);
|
||||
}
|
||||
|
||||
MR_INLINE void mr_kmutex_kset_init(void) {
|
||||
/* Register kset */
|
||||
mr_kset_register(&kroot, "mutex");
|
||||
|
||||
/* Init ktype */
|
||||
mr_ktype_init(&ktype1, kmutex_release1_kobj);
|
||||
mr_ktype_init(&ktype2, kmutex_release2_kobj);
|
||||
}
|
||||
MR_INIT_EXPORT(mr_kmutex_kset_init, MR_INIT_LEVEL_KERNEL);
|
||||
#endif /* defined(MR_USE_KOS) && defined(MR_USE_KMUTEX) */
|
||||
Reference in New Issue
Block a user