feat(kobject): Optimize kobject lookup memory.

1.Optimize the short path registration and lookup process for kernel objects using stack memory.
This commit is contained in:
MacRsh
2025-03-08 16:22:21 +08:00
parent dd832181ba
commit 2c7efd9d5d
12 changed files with 353 additions and 23 deletions

View File

@@ -22,7 +22,6 @@ extern "C" {
/* Initcall level definition */
#define MR_INIT_LEVEL_KERNEL "1"
#define MR_INIT_LEVEL_KOS "1.1"
#define MR_INIT_LEVEL_USER(_level) "2."_level
/* Initcall type */

160
include/kernel/mr_kfifo.h Normal file
View File

@@ -0,0 +1,160 @@
/**
* @copyright (c) 2024, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2024-09-06 MacRsh First version
*/
#ifndef __MR_KFIFO_H__
#define __MR_KFIFO_H__
#include <kernel/mr_kservice.h>
#include <libc/mr_compiler.h>
#include <libc/mr_types.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @addtogroup Kfifo
* @{
*/
/* Kfifo type */
typedef struct mr_kfifo {
mr_uint8_t *buf;
mr_uint32_t size;
mr_uint32_t in;
mr_uint32_t out;
} mr_kfifo_t;
/**
* @brief This function initializes a kfifo.
*
* @param kfifo The kfifo to initialize.
* @param buf The buffer of the kfifo.
* @param size The size of the kfifo.
*/
void mr_kfifo_init(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size);
/**
* @brief This function puts data into a kfifo.
*
* @param kfifo The kfifo to put data into.
* @param buf The data to put into the kfifo.
* @param size The size of the data.
* @return The number of bytes put into the kfifo.
*/
mr_uint32_t mr_kfifo_in(mr_kfifo_t *kfifo, const void *buf, mr_uint32_t size);
/**
* @brief This function takes data out of a kfifo.
*
* @param kfifo The kfifo to take data out of.
* @param buf The data to take out of the kfifo.
* @param size The size of the data.
* @return The number of bytes taken out of the kfifo.
*/
mr_uint32_t mr_kfifo_out(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size);
/**
* @brief This function puts data into a kfifo, overwriting old data.
*
* @param kfifo The kfifo to put data into.
* @param buf The data to put into the kfifo.
* @param size The size of the data.
* @return The number of bytes put into the kfifo.
*/
mr_uint32_t mr_kfifo_in_overwrite(mr_kfifo_t *kfifo, const void *buf,
mr_uint32_t size);
/**
* @brief This function peeks data out of a kfifo.
*
* @param kfifo The kfifo to peek data out of.
* @param buf The data to peek out of the kfifo.
* @param size The size of the data.
* @return The number of bytes peeked out of the kfifo.
*/
mr_uint32_t mr_kfifo_peek(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size);
/**
* @brief This function gets the size of a kfifo.
*
* @param kfifo The kfifo to get the size of.
* @return The size of the kfifo.
*/
MR_INLINE mr_uint32_t mr_kfifo_size(mr_kfifo_t *kfifo) {
return kfifo->size;
}
/**
* @brief This function gets the number of available space bytes in a kfifo.
*
* @param kfifo The kfifo to get the number of available space bytes in.
* @return The number of available space bytes in the kfifo.
*/
MR_INLINE mr_uint32_t mr_kfifo_avail(mr_kfifo_t *kfifo) {
return kfifo->size - (kfifo->in - kfifo->out);
}
/**
* @brief This function gets the number of data bytes in a kfifo.
*
* @param kfifo The kfifo to get the number of data bytes in.
* @return The number of data bytes in the kfifo.
*/
MR_INLINE mr_uint32_t mr_kfifo_len(mr_kfifo_t *kfifo) {
return kfifo->in - kfifo->out;
}
/**
* @brief This function resets a kfifo.
*
* @param kfifo The kfifo to reset.
*/
MR_INLINE void mr_kfifo_reset(mr_kfifo_t *kfifo) {
kfifo->in = kfifo->out = 0;
}
/**
* @brief This function skips data in a kfifo.
*
* @param kfifo The kfifo to skip data in.
* @param size The size of the data to skip.
* @return The number of bytes skipped.
*/
MR_INLINE mr_uint32_t mr_kfifo_skip(mr_kfifo_t *kfifo, mr_uint32_t size) {
kfifo->out += MR_MIN(size, mr_kfifo_len(kfifo));
return size;
}
/**
* @brief This function checks if a kfifo is empty.
*
* @param kfifo The kfifo to check.
* @return MR_TRUE if the kfifo is empty, MR_FALSE otherwise.
*/
MR_INLINE mr_bool_t mr_kfifo_is_empty(mr_kfifo_t *kfifo) {
return (kfifo->in == kfifo->out) ? MR_TRUE : MR_FALSE;
}
/**
* @brief This function checks if a kfifo is full.
*
* @param kfifo The kfifo to check.
* @return MR_TRUE if the kfifo is full, MR_FALSE otherwise.
*/
MR_INLINE mr_bool_t mr_kfifo_is_full(mr_kfifo_t *kfifo) {
return (kfifo->in == (kfifo->out + kfifo->size)) ? MR_TRUE : MR_FALSE;
}
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MR_KFIFO_H__ */

View File

@@ -0,0 +1,52 @@
/**
* @copyright (c) 2024, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2024-09-06 MacRsh First version
*/
#ifndef __MR_KVERSION_H__
#define __MR_KVERSION_H__
/**
* @addtogroup Kversion
* @{
*/
/* MR-X kernel version definition */
#define MR_KVERSION_MAJOR 1
#define MR_KVERSION_MINOR 0
#define MR_KVERSION_PATCH 1
/**
* @brief This macro function constructs a kernel version code.
*
* @param _major The major version.
* @param _minor The minor version.
* @param _patch The patch version.
* @return The kernel version code.
*/
#define MR_KVERSION(_major, _minor, _patch) \
((_major) << 16 | (_minor) << 8 | (_patch))
/* Kversion code */
#define MR_KVERSION_CODE \
MR_KVERSION(MR_KVERSION_MAJOR, MR_KVERSION_MINOR, MR_KVERSION_PATCH)
/**
* @brief This macro function checks if the kernel version is the same as the
* given version.
*
* @param _major The major version.
* @param _minor The minor version.
* @param _patch The patch version.
* @return MR_TRUE if the kernel version is the same as the given version,
* MR_FALSE otherwise.
*/
#define MR_KVERSION_IS(_major, _minor, _patch) \
(MR_KVERSION_CODE == MR_KVERSION(_major, _minor, _patch))
/** @} */
#endif /* __MR_KVERSION_H__ */

View File

@@ -27,7 +27,7 @@ extern "C" {
#if defined(MR_USE_KOS) && defined(MR_USE_KMUTEX)
/* Kmutex type */
typedef struct mr_kmutex {
struct mr_kobject parent;
mr_kobject_t parent;
mr_ptr_t mutex;
#if !defined(MR_CFG_KMUTEX_IMUTEX_SIZE)
#define MR_CFG_KMUTEX_IMUTEX_SIZE (64)

View File

@@ -45,6 +45,14 @@ extern "C" {
#define MR_ASSERT(_expr) ((void)0)
#endif /* defined(MR_USE_LIBC_ASSERT) */
/**
* @brief This macro function defines a static assert.
*
* @param _expr The expression.
*/
#define MR_STATIC_ASSERT(_expr) \
typedef char __mr_static_assert[(_expr) ? 1 : -1];
/** @} */
#ifdef __cplusplus

View File

@@ -41,6 +41,7 @@ typedef struct mr_memblk {
mr_size_t size;
} mr_memblk_t;
#endif /* !defined(MR_USE_3PARTY_MALLOC) */
/**
* @brief This function allocates memory.
*

View File

@@ -24,6 +24,7 @@
#include <kernel/mr_kservice.h>
#include <kernel/mr_kspinlock.h>
#include <kernel/mr_ktimer.h>
#include <kernel/mr_kversion.h>
#include <kernel/os/mr_kmutex.h>
#include <kernel/os/mr_kthread.h>

View File

@@ -24,6 +24,7 @@ extern "C" {
* @brief This function initializes a thread.
*
* @param thread The thread to be initialized.
* @param name The thread name.
* @param kthread The kthread to thread arguments.
* @param stack The thread stack.
* @param stack_size The thread stack size.

101
kernel/kfifo.c Normal file
View File

@@ -0,0 +1,101 @@
/**
* @copyright (c) 2024, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2024-09-06 MacRsh First version
*/
#include <kernel/mr_kfifo.h>
#include <libc/mr_string.h>
MR_INLINE mr_uint32_t kfifo_align_down_pow2(mr_uint32_t val) {
if (val == 0) {
return 0;
}
val |= val >> 1;
val |= val >> 2;
val |= val >> 4;
val |= val >> 8;
val |= val >> 16;
return val - (val >> 1);
}
void mr_kfifo_init(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size) {
/* Init kfifo */
kfifo->buf = buf;
kfifo->in = 0;
kfifo->out = 0;
/* Align 2^n(down) */
kfifo->size = kfifo_align_down_pow2(size);
}
mr_uint32_t mr_kfifo_in(mr_kfifo_t *kfifo, const void *buf, mr_uint32_t size) {
mr_uint32_t s;
/* Get available size */
size = MR_MIN(size, mr_kfifo_avail(kfifo));
if (size == 0) {
return 0;
}
/* In end of kfifo */
s = MR_MIN(size, kfifo->size - (kfifo->in & (kfifo->size - 1)));
mr_memcpy(kfifo->buf + (kfifo->in & (kfifo->size - 1)), buf, s);
/* In start of kfifo */
mr_memcpy(kfifo->buf, (mr_uint8_t *)buf + s, size - s);
/* Update in index */
kfifo->in += size;
return size;
}
mr_uint32_t mr_kfifo_out(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size) {
/* Peek kfifo */
size = mr_kfifo_peek(kfifo, buf, size);
/* Update out index */
kfifo->out += size;
return size;
}
mr_uint32_t mr_kfifo_in_overwrite(mr_kfifo_t *kfifo, const void *buf,
mr_uint32_t size) {
mr_uint32_t s;
/* Skip the useless data */
s = MR_MIN(size, mr_kfifo_size(kfifo));
if (s > size) {
buf = (mr_uint8_t *)buf + (size - s);
size = s;
}
/* Give space to kfifo */
s = mr_kfifo_avail(kfifo);
if (s < size) {
mr_kfifo_skip(kfifo, size - s);
}
/* In kfifo */
return mr_kfifo_in(kfifo, buf, size);
}
mr_uint32_t mr_kfifo_peek(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size) {
mr_uint32_t s;
/* Get available size */
size = MR_MIN(size, mr_kfifo_len(kfifo));
if (size == 0) {
return 0;
}
/* Out end of kfifo */
s = MR_MIN(size, kfifo->size - (kfifo->out & (kfifo->size - 1)));
mr_memcpy(buf, kfifo->buf + (kfifo->out & (kfifo->size - 1)), s);
/* Out start of kfifo */
mr_memcpy((mr_uint8_t *)buf + s, kfifo->buf, size - s);
return size;
}

View File

@@ -57,7 +57,8 @@ void mr_kobject_init(mr_kobject_t *kobj, mr_ktype_t *type) {
}
MR_INLINE mr_err_t path_alloc_varg(const char *fmt, mr_va_list args,
const char **path) {
const char **path, char *ipath,
mr_size_t ipath_len) {
int path_len;
/* Get path length */
@@ -67,9 +68,14 @@ MR_INLINE mr_err_t path_alloc_varg(const char *fmt, mr_va_list args,
}
/* Allocate path */
*path = mr_malloc(path_len + 1);
if (!(*path)) {
return -MR_ENOMEM;
if (path_len < ipath_len) {
/* Use inline path if possible */
*path = ipath;
} else {
*path = mr_malloc(path_len + 1);
if (!(*path)) {
return -MR_ENOMEM;
}
}
/* Format path */
@@ -212,7 +218,11 @@ MR_INLINE mr_err_t kobject_name_alloc(mr_kobject_t *kobj, const char *name) {
return 0;
}
MR_INLINE void path_free(const char *path) {
MR_INLINE void path_free(const char *path, char *ipath) {
if (path == ipath) {
/* Inline path not need to free */
return;
}
mr_free((char *)path);
}
@@ -246,6 +256,7 @@ MR_INLINE mr_err_t kobject_add(mr_kobject_t *kobj, mr_kobject_t *parent,
MR_INLINE mr_err_t kobject_add_varg(mr_kobject_t *kobj, mr_kobject_t *parent,
const char *fmt, mr_va_list args) {
char ipath[MR_CFG_KOBJECT_INAME_SIZE * 2];
const char *path;
mr_err_t ret;
int mask;
@@ -260,7 +271,7 @@ MR_INLINE mr_err_t kobject_add_varg(mr_kobject_t *kobj, mr_kobject_t *parent,
}
/* Allocate path */
ret = path_alloc_varg(fmt, args, &path);
ret = path_alloc_varg(fmt, args, &path, ipath, sizeof(ipath));
if (ret != 0) {
goto _exit;
}
@@ -269,7 +280,7 @@ MR_INLINE mr_err_t kobject_add_varg(mr_kobject_t *kobj, mr_kobject_t *parent,
ret = kobject_add(kobj, parent, path);
/* Free path */
path_free(path);
path_free(path, ipath);
_exit:
/* Unlock */
mr_kspinlock_unlock_irqrestore(&klock, mask);
@@ -327,6 +338,7 @@ void mr_kobject_del(mr_kobject_t *kobj) {
MR_INLINE mr_kobject_t *kobject_lookup_varg(mr_kobject_t *parent,
const char *fmt, mr_va_list args) {
char ipath[MR_CFG_KOBJECT_INAME_SIZE * 2];
const char *path, *path2;
mr_kobject_t *kobj;
mr_err_t ret;
@@ -336,7 +348,7 @@ MR_INLINE mr_kobject_t *kobject_lookup_varg(mr_kobject_t *parent,
mask = mr_kspinlock_lock_irqsave(&klock);
/* Allocate path */
ret = path_alloc_varg(fmt, args, &path);
ret = path_alloc_varg(fmt, args, &path, ipath, sizeof(ipath));
if (ret != 0) {
kobj = MR_NULL;
goto _exit;
@@ -349,7 +361,7 @@ MR_INLINE mr_kobject_t *kobject_lookup_varg(mr_kobject_t *parent,
kobj = kobject_lookup_path(&parent, &path, parent);
/* Free path */
path_free(path2);
path_free(path2, ipath);
_exit:
/* Unlock */
mr_kspinlock_unlock_irqrestore(&klock, mask);
@@ -431,7 +443,8 @@ void mr_kobject_put(mr_kobject_t *kobj) {
mr_kref_put(&kobj->ref, kobject_release_ref);
}
MR_INLINE mr_kattr_t *kobject_attr_lookup(mr_kobject_t *kobj, const char *name) {
MR_INLINE mr_kattr_t *kobject_attr_lookup(mr_kobject_t *kobj,
const char *name) {
mr_kattr_t **attrs;
mr_size_t i;
@@ -484,7 +497,7 @@ mr_ssize_t mr_kobject_attr_store(mr_kobject_t *kobj, const char *name,
if ((!kobj) || (!MR_KOBJECT_IS_INITED(kobj)) || (!name)
|| ((!buf) && (size > 0))) {
return -MR_EINVAL;
}
}
/* Lookup attribute */
attr = kobject_attr_lookup(kobj, name);
@@ -506,7 +519,6 @@ mr_err_t mr_kset_register(mr_kset_t *kset, const char *name) {
return mr_kobject_add((mr_kobject_t *)kset, (mr_kobject_t *)&kroot, name);
}
mr_kset_t *mr_kset_find(const char *name) {
/* Lookup kset in kroot */
return (mr_kset_t *)mr_kobject_lookup((mr_kobject_t *)&kroot, name);

View File

@@ -10,6 +10,7 @@
#if defined(MR_USE_KOS)
#include "FreeRTOS.h"
#include "task.h"
#include <libc/mr_assert.h>
#include <port/mr_port_thread.h>
static mr_err_t err_shift(BaseType_t ret) {
@@ -54,10 +55,7 @@ mr_err_t mr_port_thread_init(void *thread, const char *name, void *kthread,
BaseType_t ret;
/* Check inline thread size */
if (MR_CFG_KTHREAD_ITHREAD_SIZE < sizeof(StaticTask_t)) {
ret = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
return err_shift(ret);
}
MR_STATIC_ASSERT(MR_CFG_KTHREAD_ITHREAD_SIZE >= sizeof(StaticTask_t));
/* Shift arguments */
task_arguments_shift(&stack_size, &priority);

View File

@@ -73,10 +73,7 @@ mr_err_t mr_port_thread_init(void *thread, const char *name, void *kthread,
rt_err_t ret;
/* Check inline thread size */
if (MR_CFG_KTHREAD_ITHREAD_SIZE < sizeof(struct rt_thread)) {
ret = -RT_ENOMEM;
return err_shift(ret);
}
MR_STATIC_ASSERT(MR_CFG_KTHREAD_ITHREAD_SIZE >= sizeof(struct rt_thread));
/* Init thread */
ret = rt_thread_init(thread, name, thread_entry, kthread, stack, stack_size,
@@ -185,5 +182,5 @@ static void mr_main_thread_takeover(void) {
main->parameter = &kth;
mr_kthread_takeover(&kth, "main", main);
}
MR_INIT_EXPORT(mr_main_thread_takeover, MR_INIT_LEVEL_KOS);
MR_INIT_EXPORT(mr_main_thread_takeover, MR_INIT_LEVEL_USER("0"));
#endif /* defined(MR_USE_KOS) */