feat(kmutex): Added kernel mutex.

This commit is contained in:
MacRsh
2025-03-03 23:52:39 +08:00
parent ed754db9d9
commit 45cb3d5183
5 changed files with 392 additions and 2 deletions

View File

@@ -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

View 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__ */

View 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__ */

View File

@@ -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
View 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) */