fix(kos,kthread): Fixed thread lifecycle management issues.

This commit is contained in:
MacRsh
2025-02-11 23:37:47 +08:00
parent 3a4d77588c
commit d28cca8766
6 changed files with 135 additions and 115 deletions

View File

@@ -1,50 +0,0 @@
/**
* @copyright (c) 2024, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2024-09-06 MacRsh First version
*/
#ifndef __MR_HW_STACK_H__
#define __MR_HW_STACK_H__
#ifdef __cplusplus
"C" {
#endif /* __cplusplus */
/**
* @addtogroup Stack hardware interface
* @{
*/
/**
* @brief This function initialize the hardware stack.
* @param entry The entry point.
* @param stack_addr The stack address(top).
* @return The top of the stack.
*/
void *mr_hw_stack_init(void *entry, void *stack_addr);
/**
* @brief This function switch the hardware stack.
*
* @param from The old stack address(top).
* @param to The new stack address(top).
*/
void mr_hw_context_switch(void *from, void *to);
/**
* @brief This function switch the hardware stack.
*
* @param to The new stack address(top).
*/
void mr_hw_context_switch_to(void *to);
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MR_HW_STACK_H__ */

View File

@@ -54,23 +54,37 @@ typedef struct mr_kos {
} mr_kos_t;
/**
* @brief This function registers kernel os.
* @brief This function registers a kernel os.
*
* @return 0 on success, or a negative error code on failure.
*/
mr_err_t mr_kos_register(mr_kos_type_t *type);
mr_err_t mr_kos_register(mr_kos_type_t *ktype);
/**
* @brief This function gets kernel os.
* @brief This function gets a kernel os.
*
* @param kos The kernel os.
* @return The kernel os on success, or MR_NULL on failure.
*/
MR_INLINE mr_kos_t *mr_kos_get(mr_kos_t *kos) {
return (mr_kos_t *)mr_kobject_get((mr_kobject_t *)kos);
}
/**
* @brief This function puts a kernel os.
*
* @param kos The kernel os.
*/
MR_INLINE void mr_kos_put(mr_kos_t *kos) {
mr_kobject_put((mr_kobject_t *)kos);
}
/**
* @brief This function finds a kernel os.
*
* @return The kernel os.
*/
mr_kos_t *mr_kos_get(void);
/**
* @brief This function puts kernel os.
*/
void mr_kos_put(void);
mr_kos_t *mr_kos_find(void);
/**
* @brief This macro function gets the kthread operations of a kernel os.

View File

@@ -144,6 +144,25 @@ mr_err_t mr_kthread_exit(mr_kthread_t *kth);
*/
mr_kthread_t *mr_kthread_self(void);
/**
* @brief This function get a kthread.
*
* @param kth The kthread.
* @return The kthread on success, or MR_NULL on failure.
*/
MR_INLINE mr_kthread_t *mr_kthread_get(mr_kthread_t *kth) {
return (mr_kthread_t *)mr_kobject_get((mr_kobject_t *)kth);
}
/**
* @brief This function put a kthread.
*
* @param kth The kthread.
*/
MR_INLINE void mr_kthread_put(mr_kthread_t *kth) {
mr_kobject_put((mr_kobject_t *)kth);
}
/**
* @brief This function find a kthread.
*

View File

@@ -5,6 +5,7 @@
extern "C" {
#endif /* __cplusplus */
#define MR_USE_LIBC_PRINTF
#ifdef __cplusplus
}

View File

@@ -8,41 +8,36 @@
#include <kernel/kos/mr_kos.h>
static mr_kos_t kos;
static mr_kos_t kroot;
MR_INLINE void kos_init(mr_kos_t *os, mr_kos_type_t *type) {
MR_INLINE void kos_init(mr_kos_t *os, mr_kos_type_t *ktype) {
/* Init kos */
os->type = type;
os->type = ktype;
}
MR_INLINE mr_err_t kos_init_register(mr_kos_t *os, const char *name,
mr_kos_type_t *type) {
MR_INLINE mr_err_t kos_init_register(mr_kos_t *kos, const char *name,
mr_kos_type_t *ktype) {
/* Init kos */
kos_init(os, type);
kos_init(kos, ktype);
/* Init kset */
mr_kset_init((mr_kset_t *)os, MR_NULL);
mr_kset_init((mr_kset_t *)kos, MR_NULL);
/* Register kset */
return mr_kset_register((mr_kset_t *)os, name);
return mr_kset_register((mr_kset_t *)kos, name);
}
mr_err_t mr_kos_register(mr_kos_type_t *type) {
/* Check arguments */
if (MR_KOBJECT_IS_INITED(&kos) || (!type)) {
if (MR_KOBJECT_IS_INITED(&kroot) || (!type)) {
return -MR_EINVAL;
}
/* Init and register kos */
return kos_init_register(&kos, "os", type);
return kos_init_register(&kroot, "os", type);
}
mr_kos_t *mr_kos_get(void) {
/* Get kos */
return (mr_kos_t *)mr_kobject_get((mr_kobject_t *)&kos);
}
void mr_kos_put(void) {
/* Put kos */
mr_kobject_put((mr_kobject_t *)&kos);
mr_kos_t *mr_kos_find(void) {
/* Find kos in kroot */
return &kroot;
}

View File

@@ -34,6 +34,20 @@ MR_INLINE mr_err_t kthread_res_alloc(mr_kthread_t *kth, mr_size_t size) {
return 0;
}
MR_INLINE void kthread_res_free(mr_kthread_t *kth) {
const void *res;
/* If resource is inline or takeover, not need to free */
res = ((kth->res != kth->ires) && (kth->entry)) ? kth->res : MR_NULL;
if (res) {
mr_free((void *)res);
}
}
MR_INLINE mr_bool_t kthread_is_takeover(mr_kthread_t *kth) {
return (kth->res != kth->ires) && (!kth->entry);
}
MR_INLINE mr_err_t kthread_init(mr_kthread_t *kth, const char *name,
mr_ptr_t entry, mr_ptr_t args, void *stack,
mr_size_t stack_size, mr_uint32_t priority,
@@ -47,30 +61,38 @@ MR_INLINE mr_err_t kthread_init(mr_kthread_t *kth, const char *name,
return -MR_EINVAL;
}
/* Non-takeover kthread need to initialize resources */
if (!kthread_is_takeover(kth)) {
/* Alloc resource */
ret = kthread_res_alloc(kth, type->size);
if (ret != 0) {
return ret;
}
/* Init kthread resource */
ret = MR_KOS_KTH_OPS(kos)->init((void *)kth->res, name, kth, stack,
stack_size, priority, tick);
if (ret != 0) {
kthread_res_free(kth);
return ret;
}
}
/* Init kthread */
kth->priority = priority;
kth->tick = tick;
kth->entry = entry;
kth->args = args;
kth->os = kos;
/* Takeover kthread resources not need init. */
if (!kth->entry) {
return 0;
}
/* Alloc resource */
ret = kthread_res_alloc(kth, type->size);
if (ret != 0) {
return ret;
}
/* Init kthread resource */
return MR_KOS_KTH_OPS(kth->os)->init((void *)kth->res, name, kth, stack,
stack_size, priority, tick);
kth->os = mr_kos_get(kos);
return 0;
}
MR_INLINE mr_err_t kthread_del(mr_kthread_t *kth) {
/* Takeover kthread do not need to delete */
if (kthread_is_takeover(kth)) {
return 0;
}
/* Delete kthread resource */
return MR_KOS_KTH_OPS(kth->os)->del((void *)kth->res);
}
@@ -84,7 +106,7 @@ MR_INLINE mr_err_t kthread_init_add(mr_kthread_t *kth, mr_ktype_t *ktype,
mr_err_t ret;
/* Get kos */
kos = mr_kos_get();
kos = mr_kos_get(mr_kos_find());
if (!kos) {
return -MR_ENOSYS;
}
@@ -102,13 +124,15 @@ MR_INLINE mr_err_t kthread_init_add(mr_kthread_t *kth, mr_ktype_t *ktype,
/* Add kobject to kroot */
ret = mr_kobject_add((mr_kobject_t *)kth, (mr_kobject_t *)&kroot, name);
if (ret != 0) {
mr_kos_put(kos);
kthread_del(kth);
kthread_res_free(kth);
goto _exit;
}
_exit:
/* Put kos */
mr_kos_put();
mr_kos_put(kos);
return ret;
}
@@ -200,11 +224,20 @@ mr_err_t mr_kthread_del(mr_kthread_t *kth) {
}
MR_INLINE mr_err_t kthread_startup(mr_kthread_t *kth) {
/* Get kobject */
mr_kobject_get((mr_kobject_t *)kth);
mr_err_t ret;
/* Prevents run-time release(exit and cleanup) */
mr_kthread_get(kth);
mr_kthread_get(kth);
/* Startup kthread resource */
return MR_KOS_KTH_OPS(kth->os)->startup((void *)kth->res);
ret = MR_KOS_KTH_OPS(kth->os)->startup((void *)kth->res);
if (ret != 0) {
mr_kthread_put(kth);
mr_kthread_put(kth);
return ret;
}
return 0;
}
mr_err_t mr_kthread_startup(mr_kthread_t *kth) {
@@ -237,7 +270,7 @@ MR_INLINE mr_err_t kthread_yield(void) {
mr_err_t ret;
/* Get kos */
kos = mr_kos_get();
kos = mr_kos_get(mr_kos_find());
if (!kos) {
return -MR_ENOSYS;
}
@@ -246,7 +279,7 @@ MR_INLINE mr_err_t kthread_yield(void) {
ret = MR_KOS_KTH_OPS(kos)->yield();
/* Put kos */
mr_kos_put();
mr_kos_put(kos);
return ret;
}
@@ -275,7 +308,7 @@ MR_INLINE mr_err_t kthread_sleep(mr_tick_t tick) {
mr_err_t ret;
/* Get kos */
kos = mr_kos_get();
kos = mr_kos_get(mr_kos_find());
if (!kos) {
return -MR_ENOSYS;
}
@@ -284,7 +317,7 @@ MR_INLINE mr_err_t kthread_sleep(mr_tick_t tick) {
ret = MR_KOS_KTH_OPS(kos)->sleep(tick);
/* Put kos */
mr_kos_put();
mr_kos_put(kos);
return ret;
}
@@ -294,8 +327,17 @@ mr_err_t mr_kthread_sleep(mr_tick_t tick) {
}
MR_INLINE mr_err_t kthread_exit(mr_kthread_t *kth) {
mr_err_t ret;
/* Exit kthread resource */
return MR_KOS_KTH_OPS(kth->os)->exit((void *)kth->res);
ret = MR_KOS_KTH_OPS(kth->os)->exit((void *)kth->res);
if (ret != 0) {
return ret;
}
/* Free runtime(exit) */
mr_kthread_put(kth);
return 0;
}
mr_err_t mr_kthread_exit(mr_kthread_t *kth) {
@@ -313,16 +355,16 @@ MR_INLINE mr_kthread_t *kthread_self(void) {
mr_kos_t *kos;
/* Get kos */
kos = mr_kos_get();
kos = mr_kos_get(mr_kos_find());
if (!kos) {
return MR_NULL;
}
/* Get kthread self */
ret = MR_KOS_KTH_OPS(mr_kos_get())->self();
ret = MR_KOS_KTH_OPS(kos)->self();
/* Put kos */
mr_kos_put();
mr_kos_put(kos);
return ret;
}
@@ -342,8 +384,8 @@ void mr_kthread_cleanup(mr_kthread_t *kth) {
return;
}
/* Cleanup kthread */
mr_kobject_put((mr_kobject_t *)kth);
/* Free runtime(cleanup) */
mr_kthread_put(kth);
}
void mr_kthread_entry(mr_kthread_t *kth) {
@@ -354,23 +396,22 @@ void mr_kthread_entry(mr_kthread_t *kth) {
/* Call kthread entry */
((void (*)(mr_kthread_t *, void *))kth->entry)(kth, kth->args);
/* Free runtime(exit) */
mr_kthread_put(kth);
}
MR_INLINE mr_kthread_t *kthread_release_kobj(mr_kobject_t *kobj) {
mr_kthread_t *kth;
const void *res;
/* Get kthread */
kth = MR_CONTAINER_OF(kobj, mr_kthread_t, parent);
/* If resource is inline or takeover, not need to free */
res = ((kth->res != kth->ires) && (kth->entry)) ? kth->res : MR_NULL;
if (res) {
mr_free((void *)res);
}
/* Free kthread resource */
kthread_res_free(kth);
/* Put kos */
mr_kos_put();
mr_kos_put(kth->os);
return kth;
}