refactor(all): The previous writing is not good so all refactoring.
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
#ifndef __MR_HW_IRQ_H__
|
||||
#define __MR_HW_IRQ_H__
|
||||
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
"C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_CLOCK_H__
|
||||
#define __MR_CLOCK_H__
|
||||
|
||||
#include <libc/mr_errno.h>
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Clock
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Clock type */
|
||||
typedef mr_uint32_t mr_clock_t;
|
||||
typedef mr_clock_t mr_tick_t;
|
||||
#define MR_CLOCK_MAX MR_UINT32_MAX
|
||||
#define MR_TICK_MAX MR_CLOCK_MAX
|
||||
|
||||
/**
|
||||
* @brief This function increases the kclock.
|
||||
*
|
||||
* @param clock The clock to increase.
|
||||
*/
|
||||
void mr_clock_increase(mr_clock_t clock);
|
||||
|
||||
/**
|
||||
* @brief This function gets the kclock.
|
||||
*
|
||||
* @return The kclock.
|
||||
*/
|
||||
mr_clock_t mr_clock_get(void);
|
||||
|
||||
/**
|
||||
* @brief This function sets the kclock.
|
||||
*
|
||||
* @param clock The kclock to clock.
|
||||
*/
|
||||
void mr_clock_set(mr_clock_t clock);
|
||||
|
||||
/**
|
||||
* @brief This function adds a hooks to the kclock.
|
||||
*
|
||||
* @param index The index of the hooks(auto: '-1').
|
||||
* @param hook The hooks to add.
|
||||
* @return The index on success, or a negative error code on failure.
|
||||
*/
|
||||
int mr_clock_hook_add(int index, void (*hook)(void));
|
||||
|
||||
/**
|
||||
* @brief This function deletes a hooks from the kclock.
|
||||
*
|
||||
* @param index The index of the hooks.
|
||||
*/
|
||||
void mr_clock_hook_del(int index);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_CLOCK_H__ */
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_HOOKS_H__
|
||||
#define __MR_HOOKS_H__
|
||||
|
||||
#include <kernel/mr_spinlock.h>
|
||||
#include <libc/mr_errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Hook
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Hooks type */
|
||||
typedef struct mr_hooks {
|
||||
mr_spinlock_t lock;
|
||||
mr_ptr_t *hook;
|
||||
mr_size_t size;
|
||||
} mr_hooks_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initialize a hooks.
|
||||
*
|
||||
* @param _hooks The hooks.
|
||||
* @param _size The size of the hook pointers.
|
||||
*/
|
||||
#define MR_HOOKS_INIT(_hooks, _size) \
|
||||
{ MR_SPINLOCK_INIT(), (_hooks), (_size) }
|
||||
|
||||
/**
|
||||
* @brief This function initialize a hooks.
|
||||
*
|
||||
* @param hooks The hooks.
|
||||
* @param hook The hook pointers.
|
||||
* @param size The size of the hook pointers.
|
||||
*
|
||||
* @note The size is the number of the hook pointers.
|
||||
*/
|
||||
void mr_hooks_init(mr_hooks_t *hooks, mr_ptr_t *hook, mr_size_t size);
|
||||
|
||||
/**
|
||||
* @brief This function add a hook.
|
||||
*
|
||||
* @param hooks The hooks.
|
||||
* @param index The index of the hook(auto: '-1').
|
||||
* @param hook The hook.
|
||||
* @return The index on success, or a negative error code on failure.
|
||||
*/
|
||||
int mr_hooks_add(mr_hooks_t *hooks, int index, mr_ptr_t hook);
|
||||
|
||||
/**
|
||||
* @brief This function delete a hook.
|
||||
*
|
||||
* @param hooks The hooks.
|
||||
* @param index The index of the hook.
|
||||
*/
|
||||
void mr_hooks_del(mr_hooks_t *hooks, int index);
|
||||
|
||||
/**
|
||||
* @brief This macro function iterates through the hooks.
|
||||
*
|
||||
* @param _i The index.
|
||||
* @param _hooks The hooks.
|
||||
* @param _hook The hook.
|
||||
*/
|
||||
#define MR_HOOKS_EACH(_i, _hooks, _hook) \
|
||||
for ((_i) = 0, (_hook) = (_hooks)->hook[(_i)]; (_i) < (_hooks)->size; \
|
||||
(_i)++, (_hook) = (_hooks)->hook[(_i)])
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_HOOKS_H__ */
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __MR_INITCALL_H__
|
||||
#define __MR_INITCALL_H__
|
||||
|
||||
#include <kernel/mr_compiler.h>
|
||||
#include <libc/mr_compiler.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -27,19 +27,19 @@ extern "C" {
|
||||
/* Initcall type */
|
||||
typedef struct mr_initcall {
|
||||
const char *name;
|
||||
void (*fn)(void);
|
||||
void (*entry)(void);
|
||||
} mr_initcall_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function defines an initcall.
|
||||
*
|
||||
* @param _fn The function of the initcall.
|
||||
* @param _entry The function of the initcall.
|
||||
* @param _level The level of the initcall.
|
||||
*/
|
||||
#define MR_INIT_EXPORT(_fn, _level) \
|
||||
MR_USED const mr_initcall_t __mr_initcall_##_fn MR_SECTION( \
|
||||
#define MR_INIT_EXPORT(_entry, _level) \
|
||||
MR_USED const mr_initcall_t __mr_initcall_##_entry MR_SECTION( \
|
||||
"mr_initcall." _level) \
|
||||
= {#_fn, _fn}
|
||||
= {.name = #_entry, .entry = (_entry)}
|
||||
|
||||
/**
|
||||
* @brief This function does initcalls(kernel).
|
||||
|
||||
56
include/kernel/mr_kclock.h
Normal file
56
include/kernel/mr_kclock.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KCLOCK_H__
|
||||
#define __MR_KCLOCK_H__
|
||||
|
||||
#include <libc/mr_errno.h>
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kclock
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Clock type */
|
||||
typedef mr_uint32_t mr_tick_t;
|
||||
#define MR_TICK_MAX MR_UINT32_MAX
|
||||
|
||||
/**
|
||||
* @brief This function increases the clock tick.
|
||||
*
|
||||
* @param tick The tick to increase.
|
||||
*/
|
||||
void mr_kclock_increase(mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function gets the clock tick.
|
||||
*
|
||||
* @return The tick.
|
||||
*/
|
||||
mr_tick_t mr_kclock_tick(void);
|
||||
|
||||
/**
|
||||
* @brief This function adds a hook to the clock.
|
||||
*
|
||||
* @param entry The hook entry.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kclock_hook_add(void (*entry)(void));
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KCLOCK_H__ */
|
||||
160
include/kernel/mr_kfifo.h
Normal file
160
include/kernel/mr_kfifo.h
Normal 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__ */
|
||||
81
include/kernel/mr_khook.h
Normal file
81
include/kernel/mr_khook.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KHOOK_H__
|
||||
#define __MR_KHOOK_H__
|
||||
|
||||
#include "mr_spinlock.h"
|
||||
#include <libc/mr_errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Khook
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Khook type */
|
||||
typedef struct mr_khook {
|
||||
mr_spinlock_t lock;
|
||||
mr_ptr_t *entry;
|
||||
mr_size_t size;
|
||||
mr_size_t next;
|
||||
} mr_khook_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initialize a hook.
|
||||
*
|
||||
* @param _entry The hook entry.
|
||||
* @param _size The size of the entry pointers.
|
||||
*/
|
||||
#define MR_KHOOK_INIT(_entry, _size) \
|
||||
{ \
|
||||
.lock = MR_SPINLOCK_INIT(), .entry = (_entry), .size = (_size), \
|
||||
.next = 0 \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function initialize a khook.
|
||||
*
|
||||
* @param khook The khook.
|
||||
* @param entry The entry pointers.
|
||||
* @param size The size of the entry pointers.
|
||||
*
|
||||
* @note The size is the number of the entry pointers.
|
||||
*/
|
||||
void mr_khook_init(mr_khook_t *khook, mr_ptr_t *entry, mr_size_t size);
|
||||
|
||||
/**
|
||||
* @brief This function add a entry to the khook.
|
||||
*
|
||||
* @param khook The khook.
|
||||
* @param entry The entry.
|
||||
* @returns 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_khook_add(mr_khook_t *khook, mr_ptr_t entry);
|
||||
|
||||
/**
|
||||
* @brief This macro function iterates through the hook.
|
||||
*
|
||||
* @param _i The index.
|
||||
* @param _entry The entry.
|
||||
* @param _hook The hook.
|
||||
*/
|
||||
#define MR_KHOOK_EACH(_i, _entry, _hook) \
|
||||
for ((_i) = 0, (_entry) = (_hook)->entry[(_i)]; (_i) < (_hook)->next; \
|
||||
(_i)++, (_entry) = (_hook)->entry[(_i)])
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KHOOK_H__ */
|
||||
@@ -6,10 +6,11 @@
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_LIST_H__
|
||||
#define __MR_LIST_H__
|
||||
#ifndef __MR_KLIST_H__
|
||||
#define __MR_KLIST_H__
|
||||
|
||||
#include <kernel/mr_service.h>
|
||||
#include <kernel/mr_kservice.h>
|
||||
#include <libc/mr_compiler.h>
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -17,30 +18,30 @@ extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup List
|
||||
* @addtogroup Klist
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Double list type */
|
||||
typedef struct mr_list {
|
||||
struct mr_list *next;
|
||||
struct mr_list *prev;
|
||||
} mr_list_t;
|
||||
typedef struct mr_klist {
|
||||
struct mr_klist *next;
|
||||
struct mr_klist *prev;
|
||||
} mr_klist_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a list.
|
||||
*
|
||||
* @param _list The list to initialize.
|
||||
* @param _klist The list to initialize.
|
||||
*/
|
||||
#define MR_LIST_INIT(_list) \
|
||||
{ &(_list), &(_list) }
|
||||
#define MR_KLIST_INIT(_klist) \
|
||||
{ .next = (_klist), .prev = (_klist) }
|
||||
|
||||
/**
|
||||
* @brief This function initializes a list.
|
||||
*
|
||||
* @param entry The element to initialize.
|
||||
*/
|
||||
MR_INLINE void mr_list_init(mr_list_t *entry) {
|
||||
MR_INLINE void mr_klist_init(mr_klist_t *entry) {
|
||||
entry->next = entry->prev = entry;
|
||||
}
|
||||
|
||||
@@ -49,8 +50,10 @@ MR_INLINE void mr_list_init(mr_list_t *entry) {
|
||||
*
|
||||
* @param head The list head.
|
||||
* @param entry The element to add.
|
||||
*
|
||||
* @note Adds to the end of the list.
|
||||
*/
|
||||
MR_INLINE void mr_list_add(mr_list_t *head, mr_list_t *entry) {
|
||||
MR_INLINE void mr_klist_add(mr_klist_t *head, mr_klist_t *entry) {
|
||||
head->prev->next = entry;
|
||||
entry->prev = head->prev;
|
||||
head->prev = entry;
|
||||
@@ -58,12 +61,14 @@ MR_INLINE void mr_list_add(mr_list_t *head, mr_list_t *entry) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function adds an element to the head of the list.
|
||||
* @brief This function inserts an element into the list.
|
||||
*
|
||||
* @param head The list head.
|
||||
* @param entry The element to add.
|
||||
* @param entry The element to insert.
|
||||
*
|
||||
* @note Inserts to the beginning of the list.
|
||||
*/
|
||||
MR_INLINE void mr_list_add_head(mr_list_t *head, mr_list_t *entry) {
|
||||
MR_INLINE void mr_klist_insert(mr_klist_t *head, mr_klist_t *entry) {
|
||||
head->next->prev = entry;
|
||||
entry->next = head->next;
|
||||
head->next = entry;
|
||||
@@ -75,7 +80,7 @@ MR_INLINE void mr_list_add_head(mr_list_t *head, mr_list_t *entry) {
|
||||
*
|
||||
* @param entry The element to remove.
|
||||
*/
|
||||
MR_INLINE void mr_list_del(mr_list_t *entry) {
|
||||
MR_INLINE void mr_klist_del(mr_klist_t *entry) {
|
||||
entry->prev->next = entry->next;
|
||||
entry->next->prev = entry->prev;
|
||||
entry->next = entry->prev = entry;
|
||||
@@ -87,7 +92,7 @@ MR_INLINE void mr_list_del(mr_list_t *entry) {
|
||||
* @param new The new element.
|
||||
* @param old The old element.
|
||||
*/
|
||||
MR_INLINE void mr_list_replace(mr_list_t *new, mr_list_t *old) {
|
||||
MR_INLINE void mr_klist_replace(mr_klist_t *new, mr_klist_t *old) {
|
||||
new->next = old->next;
|
||||
new->next->prev = new;
|
||||
new->prev = old->prev;
|
||||
@@ -101,16 +106,16 @@ MR_INLINE void mr_list_replace(mr_list_t *new, mr_list_t *old) {
|
||||
* @param entry1 The first element.
|
||||
* @param entry2 The second element.
|
||||
*/
|
||||
MR_INLINE void mr_list_swap(mr_list_t *entry1, mr_list_t *entry2) {
|
||||
mr_list_t *tmp;
|
||||
MR_INLINE void mr_klist_swap(mr_klist_t *entry1, mr_klist_t *entry2) {
|
||||
mr_klist_t *tmp;
|
||||
|
||||
tmp = entry2->prev;
|
||||
mr_list_del(entry2);
|
||||
mr_list_replace(entry1, entry2);
|
||||
mr_klist_del(entry2);
|
||||
mr_klist_replace(entry1, entry2);
|
||||
if (tmp == entry1) {
|
||||
tmp = entry2;
|
||||
}
|
||||
mr_list_add(tmp, entry1);
|
||||
mr_klist_add(tmp, entry1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,21 +123,12 @@ MR_INLINE void mr_list_swap(mr_list_t *entry1, mr_list_t *entry2) {
|
||||
*
|
||||
* @param entry The element to move.
|
||||
* @param head The list head.
|
||||
*/
|
||||
MR_INLINE void mr_list_move(mr_list_t *entry, mr_list_t *head) {
|
||||
mr_list_del(entry);
|
||||
mr_list_add(head, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function moves an element to the head of the list.
|
||||
*
|
||||
* @param entry The element to move.
|
||||
* @param head The list head.
|
||||
* @note Move to the end of the list.
|
||||
*/
|
||||
MR_INLINE void mr_list_move_head(mr_list_t *entry, mr_list_t *head) {
|
||||
mr_list_del(entry);
|
||||
mr_list_add_head(head, entry);
|
||||
MR_INLINE void mr_klist_move(mr_klist_t *entry, mr_klist_t *head) {
|
||||
mr_klist_del(entry);
|
||||
mr_klist_add(head, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,52 +137,8 @@ MR_INLINE void mr_list_move_head(mr_list_t *entry, mr_list_t *head) {
|
||||
* @param head The list head.
|
||||
* @return MR_TRUE on empty, MR_FALSE otherwise.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_list_is_empty(mr_list_t *head) {
|
||||
return head->next == head ? MR_TRUE : MR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function rotates the list to the left.
|
||||
*
|
||||
* @param head The list head.
|
||||
*/
|
||||
MR_INLINE void mr_list_rotate_left(mr_list_t *head) {
|
||||
mr_list_t *tmp;
|
||||
|
||||
if (!mr_list_is_empty(head)) {
|
||||
tmp = head->next;
|
||||
mr_list_move_head(tmp, head);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function rotates the list to the right.
|
||||
*
|
||||
* @param head The list head.
|
||||
*/
|
||||
MR_INLINE void mr_list_rotate_right(mr_list_t *head) {
|
||||
mr_list_t *tmp;
|
||||
|
||||
if (!mr_list_is_empty(head)) {
|
||||
tmp = head->prev;
|
||||
mr_list_move(tmp, head);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function splices a list into another list.
|
||||
*
|
||||
* @param list The list to splice.
|
||||
* @param head The list head.
|
||||
*/
|
||||
MR_INLINE void mr_list_splice(mr_list_t *list, mr_list_t *head) {
|
||||
mr_list_t *tmp;
|
||||
|
||||
tmp = head->prev;
|
||||
head->prev->next = list;
|
||||
head->prev = list->prev;
|
||||
list->prev->next = head;
|
||||
list->prev = tmp;
|
||||
MR_INLINE mr_bool_t mr_klist_is_empty(mr_klist_t *head) {
|
||||
return (head->next == head) ? MR_TRUE : MR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,7 +149,7 @@ MR_INLINE void mr_list_splice(mr_list_t *list, mr_list_t *head) {
|
||||
* @param _member The member of the element.
|
||||
* @return The container of the element.
|
||||
*/
|
||||
#define MR_LIST_ENTRY(_ptr, _type, _member) \
|
||||
#define MR_KLIST_ENTRY(_ptr, _type, _member) \
|
||||
MR_CONTAINER_OF(_ptr, _type, _member)
|
||||
|
||||
/**
|
||||
@@ -206,7 +158,7 @@ MR_INLINE void mr_list_splice(mr_list_t *list, mr_list_t *head) {
|
||||
* @param _pos The pointer to the element.
|
||||
* @param _head The list head.
|
||||
*/
|
||||
#define MR_LIST_FOR_EACH(_pos, _head) \
|
||||
#define MR_KLIST_FOR_EACH(_pos, _head) \
|
||||
for ((_pos) = (_head)->next; (_pos) != (_head); (_pos) = (_pos)->next)
|
||||
|
||||
/**
|
||||
@@ -216,7 +168,7 @@ MR_INLINE void mr_list_splice(mr_list_t *list, mr_list_t *head) {
|
||||
* @param _n The pointer to the next element.
|
||||
* @param _head The list head.
|
||||
*/
|
||||
#define MR_LIST_FOR_EACH_SAFE(_pos, _n, _head) \
|
||||
#define MR_KLIST_FOR_EACH_SAFE(_pos, _n, _head) \
|
||||
for ((_pos) = (_head)->next, (_n) = (_pos)->next; (_pos) != (_head); \
|
||||
(_pos) = (_n), (_n) = (_pos)->next)
|
||||
|
||||
@@ -226,4 +178,4 @@ MR_INLINE void mr_list_splice(mr_list_t *list, mr_list_t *head) {
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_LIST_H__ */
|
||||
#endif /* __MR_KLIST_H__ */
|
||||
120
include/kernel/mr_kmap.h
Normal file
120
include/kernel/mr_kmap.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KMAP_H__
|
||||
#define __MR_KMAP_H__
|
||||
|
||||
#include <libc/mr_compiler.h>
|
||||
#include <libc/mr_errno.h>
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kmap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Knode type */
|
||||
typedef struct mr_knode {
|
||||
mr_uint32_t key;
|
||||
void *value;
|
||||
struct mr_knode *next;
|
||||
} mr_knode_t;
|
||||
|
||||
/* Kmap type */
|
||||
typedef struct mr_kmap {
|
||||
mr_knode_t **b;
|
||||
mr_size_t size;
|
||||
mr_size_t count;
|
||||
mr_f32_t load_factor;
|
||||
} mr_kmap_t;
|
||||
|
||||
/**
|
||||
* @brief This function initializes a kmap.
|
||||
*
|
||||
* @param kmap The kmap to initialize.
|
||||
* @param size The size of the kmap.
|
||||
* @param load_factor The load factor of the kmap.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmap_init(mr_kmap_t *kmap, mr_size_t size, mr_f32_t load_factor);
|
||||
|
||||
/**
|
||||
* @brief This function adds a key-value pair to the kmap.
|
||||
*
|
||||
* @param kmap The kmap to add the key-value pair to.
|
||||
* @param key The key to add.
|
||||
* @param value The value to add.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmap_add(mr_kmap_t *kmap, mr_uint32_t key, void *value);
|
||||
|
||||
/**
|
||||
* @brief This function deletes a key-value pair from the kmap.
|
||||
*
|
||||
* @param kmap The kmap to delete the key-value pair from.
|
||||
* @param key The key to delete.
|
||||
* @return The value of the deleted key-value pair, or MR_NULL if not found.
|
||||
*/
|
||||
void *mr_kmap_del(mr_kmap_t *kmap, mr_uint32_t key);
|
||||
|
||||
/**
|
||||
* @brief This function gets the value of a key from the kmap.
|
||||
*
|
||||
* @param kmap The kmap to get the value from.
|
||||
* @param key The key to get the value of.
|
||||
* @return The value of the key, or MR_NULL if not found.
|
||||
*/
|
||||
void *mr_kmap_value(mr_kmap_t *kmap, mr_uint32_t key);
|
||||
|
||||
/**
|
||||
* @brief This function clears the kmap.
|
||||
*
|
||||
* @param kmap The kmap to clear.
|
||||
*/
|
||||
void mr_kmap_clear(mr_kmap_t *kmap);
|
||||
|
||||
/**
|
||||
* @brief This function shrinks the kmap.
|
||||
*
|
||||
* @param kmap The kmap to shrink.
|
||||
* @param size The new size of the kmap.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kmap_shrink(mr_kmap_t *kmap, mr_size_t size);
|
||||
|
||||
/**
|
||||
* @brief This function gets the size of the kmap.
|
||||
*
|
||||
* @param kmap The kmap to get the size of.
|
||||
* @return The size of the kmap.
|
||||
*/
|
||||
MR_INLINE mr_size_t mr_kmap_count(mr_kmap_t *kmap) {
|
||||
return kmap->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function checks if the kmap is empty.
|
||||
*
|
||||
* @param kmap The kmap to check.
|
||||
* @return MR_TRUE if the kmap is empty, MR_FALSE otherwise.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_kmap_is_empty(mr_kmap_t *kmap) {
|
||||
return (kmap->count == 0) ? MR_TRUE : MR_FALSE;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KMAP_H__ */
|
||||
@@ -9,8 +9,8 @@
|
||||
#ifndef __MR_KOBJECT_H__
|
||||
#define __MR_KOBJECT_H__
|
||||
|
||||
#include <kernel/mr_list.h>
|
||||
#include <kernel/mr_lockref.h>
|
||||
#include <kernel/mr_klist.h>
|
||||
#include <kernel/mr_kref.h>
|
||||
#include <libc/mr_errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -49,9 +49,9 @@ typedef struct mr_kobject {
|
||||
char iname[MR_CFG_KOBJECT_INAME_SIZE];
|
||||
struct mr_kobject *parent;
|
||||
mr_ktype_t *type;
|
||||
mr_lockref_t ref;
|
||||
mr_list_t entry;
|
||||
mr_list_t list;
|
||||
mr_klist_t entry;
|
||||
mr_klist_t list;
|
||||
mr_kref_t ref;
|
||||
} mr_kobject_t;
|
||||
|
||||
/* Kset type */
|
||||
@@ -84,10 +84,10 @@ void mr_ktype_init(mr_ktype_t *type, void (*release)(mr_kobject_t *));
|
||||
#define MR_KOBJECT_INIT(_kobj, _type) \
|
||||
{ \
|
||||
.magic = MR_KOBJECT_MAGIC, \
|
||||
.name = {.str = (_kobj).iname, .len = 0, .hash = 0}, \
|
||||
.parent = &(_kobj), .type = (_type), .ref = MR_LOCKREF_INIT(), \
|
||||
.entry = MR_LIST_INIT((_kobj).entry), \
|
||||
.list = MR_LIST_INIT((_kobj).list) \
|
||||
.name = {.str = (_kobj)->iname, .len = 0, .hash = 0}, \
|
||||
.parent = (_kobj), .type = (_type), \
|
||||
.entry = MR_KLIST_INIT(&(_kobj)->entry), \
|
||||
.list = MR_KLIST_INIT(&(_kobj)->list), .ref = MR_KREF_INIT() \
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,6 +127,16 @@ mr_err_t mr_kobject_add(mr_kobject_t *kobj, mr_kobject_t *parent,
|
||||
*/
|
||||
void mr_kobject_del(mr_kobject_t *kobj);
|
||||
|
||||
/**
|
||||
* @brief This function looks up a kobject.
|
||||
*
|
||||
* @param parent The parent kobject.
|
||||
* @param fmt The format string(path).
|
||||
* @param ... The format arguments.
|
||||
* @return The kobject on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_kobject_t *mr_kobject_lookup(mr_kobject_t *parent, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief This function gets a kobject.
|
||||
*
|
||||
@@ -142,6 +152,22 @@ mr_kobject_t *mr_kobject_get(mr_kobject_t *kobj);
|
||||
*/
|
||||
void mr_kobject_put(mr_kobject_t *kobj);
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the name of a kobject.
|
||||
*
|
||||
* @param _kobj The kobject.
|
||||
* @return The name of the kobject.
|
||||
*/
|
||||
#define MR_KOBJECT_NAME(_kobj) (((mr_kobject_t *)(_kobj))->name.str)
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the parent of a kobject.
|
||||
*
|
||||
* @param _kobj The kobject.
|
||||
* @return The parent of the kobject.
|
||||
*/
|
||||
#define MR_KOBJECT_PARENT(_kobj) (((mr_kobject_t *)(_kobj))->parent)
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a kset.
|
||||
*
|
||||
@@ -149,9 +175,7 @@ void mr_kobject_put(mr_kobject_t *kobj);
|
||||
* @param _type The ktype.
|
||||
*/
|
||||
#define MR_KSET_INIT(_kset, _type) \
|
||||
{ \
|
||||
.parent = MR_KOBJECT_INIT((_kset).parent, (_type)) \
|
||||
}
|
||||
{ .parent = MR_KOBJECT_INIT(&(_kset)->parent, (_type)) }
|
||||
|
||||
/**
|
||||
* @brief This function initializes a kset.
|
||||
@@ -170,6 +194,14 @@ void mr_kset_init(mr_kset_t *kset, mr_ktype_t *type);
|
||||
*/
|
||||
mr_err_t mr_kset_register(mr_kset_t *kset, const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function finds a kset.
|
||||
*
|
||||
* @param name The name.
|
||||
* @returns The kset on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_kset_t *mr_kset_find(const char *name);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
38
include/kernel/mr_kprintf.h
Normal file
38
include/kernel/mr_kprintf.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KPRINTF_H__
|
||||
#define __MR_KPRINTF_H__
|
||||
|
||||
#include <libc/mr_stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kprintf
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function prints a formatted string.
|
||||
*
|
||||
* @param fmt The format string.
|
||||
* @param ... The arguments.
|
||||
* @return The number of characters printed.
|
||||
*/
|
||||
int mr_kprintf(const char *fmt, ...);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KPRINTF_H__ */
|
||||
73
include/kernel/mr_kref.h
Normal file
73
include/kernel/mr_kref.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KREF_H__
|
||||
#define __MR_KREF_H__
|
||||
|
||||
#include <libc/mr_atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kref
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Lockref type */
|
||||
typedef mr_atomic_t mr_kref_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a kref.
|
||||
*/
|
||||
#define MR_KREF_INIT() MR_ATOMIC_INIT(1)
|
||||
|
||||
/**
|
||||
* @brief This function initializes a kref.
|
||||
*
|
||||
* @param kref The kref to initialize.
|
||||
*/
|
||||
MR_INLINE void mr_kref_init(mr_kref_t *kref) {
|
||||
mr_atomic_init(kref, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function gets a kref.
|
||||
*
|
||||
* @param kref The kref to get.
|
||||
*/
|
||||
MR_INLINE void mr_kref_get(mr_kref_t *kref) {
|
||||
mr_atomic_fetch_add(kref, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function puts a kref.
|
||||
*
|
||||
* @param kref The kref to put.
|
||||
* @param release The release function to call.
|
||||
* @return MR_TRUE on end of lifecycle, MR_FALSE otherwise.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_kref_put(mr_kref_t *kref, void (*release)(mr_kref_t *)) {
|
||||
mr_atomic_t ret;
|
||||
|
||||
ret = mr_atomic_fetch_sub(kref, 1);
|
||||
if ((ret == 1) && (release != MR_NULL)) {
|
||||
release(kref);
|
||||
return MR_TRUE;
|
||||
}
|
||||
return MR_FALSE;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KREF_H__ */
|
||||
@@ -9,8 +9,6 @@
|
||||
#ifndef __MR_SERVICE_H__
|
||||
#define __MR_SERVICE_H__
|
||||
|
||||
#include <kernel/mr_compiler.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
@@ -90,6 +88,24 @@ extern "C" {
|
||||
*/
|
||||
#define MR_MAKE_LOCAL(_type, ...) (&((_type){__VA_ARGS__}))
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the minimum value.
|
||||
*
|
||||
* @param _a The first value.
|
||||
* @param _b The second value.
|
||||
* @return The minimum value.
|
||||
*/
|
||||
#define MR_MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the maximum value.
|
||||
*
|
||||
* @param _a The first value.
|
||||
* @param _b The second value.
|
||||
* @return The maximum value.
|
||||
*/
|
||||
#define MR_MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
105
include/kernel/mr_ktimer.h
Normal file
105
include/kernel/mr_ktimer.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KTIMER_H__
|
||||
#define __MR_KTIMER_H__
|
||||
|
||||
#include <kernel/mr_kclock.h>
|
||||
#include <kernel/mr_kobject.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Ktimer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Periodic definition */
|
||||
#define MR_KTIMER_PERIODIC (1U << 31)
|
||||
|
||||
/* Ktimer type */
|
||||
typedef struct mr_ktimer {
|
||||
mr_kobject_t parent;
|
||||
mr_klist_t list;
|
||||
mr_tick_t init_tick;
|
||||
mr_tick_t timeout_tick;
|
||||
mr_ptr_t entry;
|
||||
mr_ptr_t args;
|
||||
} mr_ktimer_t;
|
||||
|
||||
/**
|
||||
* @brief This function initialize a ktimer.
|
||||
*
|
||||
* @param ktimer The ktimer.
|
||||
* @param name The ktimer name.
|
||||
* @param entry The ktimer entry.
|
||||
* @param args The ktimer args.
|
||||
* @param tick The ktimer tick(period: 'tick | MR_KTIMER_PERIODIC').
|
||||
* @returns 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_ktimer_init(mr_ktimer_t *ktimer, const char *name,
|
||||
void (*entry)(mr_ktimer_t *, void *), void *args,
|
||||
mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function create a timer.
|
||||
*
|
||||
* @param name The timer name.
|
||||
* @param entry The timer entry.
|
||||
* @param args The timer args.
|
||||
* @param tick The timer tick.
|
||||
* @return The timer on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_ktimer_t *mr_ktimer_create(const char *name,
|
||||
void (*entry)(mr_ktimer_t *, void *), void *args,
|
||||
mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function delete a ktimer.
|
||||
*
|
||||
* @param ktimer The ktimer.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_ktimer_del(mr_ktimer_t *ktimer);
|
||||
|
||||
/**
|
||||
* @brief This function start a ktimer.
|
||||
*
|
||||
* @param ktimer The ktimer.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_ktimer_start(mr_ktimer_t *ktimer);
|
||||
|
||||
/**
|
||||
* @brief This function stop a ktimer.
|
||||
*
|
||||
* @param ktimer The ktimer.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_ktimer_stop(mr_ktimer_t *ktimer);
|
||||
|
||||
/**
|
||||
* @brief This function set a ktimer tick.
|
||||
*
|
||||
* @param ktimer The ktimer.
|
||||
* @param tick The ktimer tick.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note If the ktimer is running, it will be stopped.
|
||||
*/
|
||||
mr_err_t mr_ktimer_tick_set(mr_ktimer_t *ktimer, mr_tick_t tick);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KTIMER_H__ */
|
||||
@@ -1,150 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_LOCKREF_H__
|
||||
#define __MR_LOCKREF_H__
|
||||
|
||||
#include <kernel/mr_spinlock.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Lockref
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Lockref type */
|
||||
typedef struct mr_lockref {
|
||||
mr_spinlock_t lock;
|
||||
mr_atomic_t count;
|
||||
} mr_lockref_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a lockref.
|
||||
*/
|
||||
#define MR_LOCKREF_INIT() \
|
||||
{ MR_SPINLOCK_INIT(), 1 }
|
||||
|
||||
/**
|
||||
* @brief This function initializes a lockref.
|
||||
*
|
||||
* @param lockref The lockref to initialize.
|
||||
*/
|
||||
MR_INLINE void mr_lockref_init(mr_lockref_t *lockref) {
|
||||
mr_spinlock_init(&lockref->lock);
|
||||
mr_atomic_init(&lockref->count, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function tries to lock a lockref.
|
||||
*
|
||||
* @param lockref The lockref to lock.
|
||||
* @return MR_TRUE on success, MR_FALSE on failure.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_lockref_trylock(mr_lockref_t *lockref) {
|
||||
return mr_spinlock_trylock(&lockref->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function locks a lockref.
|
||||
*
|
||||
* @param lockref The lockref to lock.
|
||||
*/
|
||||
MR_INLINE void mr_lockref_lock(mr_lockref_t *lockref) {
|
||||
mr_spinlock_lock(&lockref->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function unlocks a lockref.
|
||||
*
|
||||
* @param lockref The lockref to unlock.
|
||||
*/
|
||||
MR_INLINE void mr_lockref_unlock(mr_lockref_t *lockref) {
|
||||
mr_spinlock_unlock(&lockref->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function gets a locked lockref.
|
||||
*
|
||||
* @param lockref The lockref to get.
|
||||
*/
|
||||
MR_INLINE void mr_lockref_get_locked(mr_lockref_t *lockref) {
|
||||
mr_atomic_fetch_add(&lockref->count, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function puts a locked lockref.
|
||||
*
|
||||
* @param lockref The lockref to put.
|
||||
* @param release The release function to call.
|
||||
* @return MR_TRUE on end of lifecycle, MR_FALSE otherwise.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_lockref_put_locked(mr_lockref_t *lockref,
|
||||
void (*release)(mr_lockref_t *)) {
|
||||
if (mr_atomic_load(&lockref->count) > 1) {
|
||||
mr_atomic_fetch_sub(&lockref->count, 1);
|
||||
return MR_FALSE;
|
||||
}
|
||||
/* End of lifecycle */
|
||||
if (release != MR_NULL) {
|
||||
release(lockref);
|
||||
}
|
||||
return MR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function gets a lockref.
|
||||
*
|
||||
* @param lockref The lockref to get.
|
||||
*/
|
||||
MR_INLINE void mr_lockref_get(mr_lockref_t *lockref) {
|
||||
mr_lockref_lock(lockref);
|
||||
mr_lockref_get_locked(lockref);
|
||||
mr_lockref_unlock(lockref);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function puts a lockref.
|
||||
*
|
||||
* @param lockref The lockref to put.
|
||||
* @param release The release function to call.
|
||||
* @return MR_TRUE on end of lifecycle, MR_FALSE otherwise.
|
||||
*
|
||||
* @note If the lockref will be zero, it will be not unlocked.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_lockref_put(mr_lockref_t *lockref,
|
||||
void (*release)(mr_lockref_t *)) {
|
||||
int ret;
|
||||
|
||||
mr_lockref_lock(lockref);
|
||||
ret = mr_lockref_put_locked(lockref, release);
|
||||
if (!ret) {
|
||||
mr_lockref_unlock(lockref);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function gets the count of a lockref.
|
||||
*
|
||||
* @param lockref The lockref to get.
|
||||
* @return The count of the lockref.
|
||||
*/
|
||||
MR_INLINE mr_atomic_t mr_lockref_count(mr_lockref_t *lockref) {
|
||||
return mr_atomic_load(&lockref->count);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_LOCKREF_H__ */
|
||||
@@ -1,112 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_RWLOCK_H__
|
||||
#define __MR_RWLOCK_H__
|
||||
|
||||
#include <kernel//mr_atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Rwlock
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Rwlock type */
|
||||
typedef mr_atomic_t mr_rwlock_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a rwlock.
|
||||
*/
|
||||
#define MR_RWLOCK_INIT() MR_ATOMIC_INIT(0)
|
||||
|
||||
/**
|
||||
* @brief This function initializes a rwlock.
|
||||
*
|
||||
* @param lock The rwlock to initialize.
|
||||
*/
|
||||
MR_INLINE void mr_rwlock_init(mr_rwlock_t *lock) {
|
||||
mr_atomic_init(lock, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function locks a rwlock for reading.
|
||||
*
|
||||
* @param lock The rwlock to lock.
|
||||
*/
|
||||
MR_INLINE void mr_rwlock_read_lock(mr_rwlock_t *lock) {
|
||||
while (mr_atomic_fetch_add(lock, 1) & (1U << 31)) {
|
||||
mr_atomic_fetch_sub(lock, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function unlocks a rwlock for reading.
|
||||
*
|
||||
* @param lock The rwlock to unlock.
|
||||
*/
|
||||
MR_INLINE void mr_rwlock_read_unlock(mr_rwlock_t *lock) {
|
||||
mr_atomic_fetch_sub(lock, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function unlocks a rwlock for reading.
|
||||
*
|
||||
* @param lock The rwlock to unlock.
|
||||
* @return MR_TRUE on success, MR_FALSE on failure.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_rwlock_read_trylock(mr_rwlock_t *lock) {
|
||||
if (mr_atomic_fetch_add(lock, 1) & (1U << 31)) {
|
||||
mr_atomic_fetch_sub(lock, 1);
|
||||
return MR_FALSE;
|
||||
}
|
||||
return MR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function locks a rwlock for writing.
|
||||
*
|
||||
* @param lock The rwlock to lock.
|
||||
*/
|
||||
MR_INLINE void mr_rwlock_write_lock(mr_rwlock_t *lock) {
|
||||
while (mr_atomic_fetch_or(lock, (mr_atomic_t)(1U << 31))) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function unlocks a rwlock for writing.
|
||||
*
|
||||
* @param lock The rwlock to unlock.
|
||||
*/
|
||||
MR_INLINE void mr_rwlock_write_unlock(mr_rwlock_t *lock) {
|
||||
mr_atomic_fetch_and(lock, (mr_atomic_t)(~(1U << 31)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function unlocks a rwlock for writing.
|
||||
*
|
||||
* @param lock The rwlock to unlock.
|
||||
* @return MR_TRUE on success, MR_FALSE on failure.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_rwlock_write_trylock(mr_rwlock_t *lock) {
|
||||
if (mr_atomic_fetch_or(lock, (mr_atomic_t)(1U << 31))) {
|
||||
return MR_FALSE;
|
||||
}
|
||||
return MR_TRUE;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_RWLOCK_H__ */
|
||||
136
include/kernel/mr_slist.h
Normal file
136
include/kernel/mr_slist.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_SLIST_H__
|
||||
#define __MR_SLIST_H__
|
||||
|
||||
#include <kernel/mr_kservice.h>
|
||||
#include <libc/mr_compiler.h>
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Slist
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Single list type */
|
||||
typedef struct mr_slist {
|
||||
struct mr_slist *next;
|
||||
} mr_slist_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a single list.
|
||||
*
|
||||
* @param _slist The list to initialize.
|
||||
*/
|
||||
#define MR_SLIST_INIT(_slist) \
|
||||
{ .next = MR_NULL }
|
||||
|
||||
/**
|
||||
* @brief This function initializes a single list.
|
||||
*
|
||||
* @param entry The element to initialize.
|
||||
*/
|
||||
MR_INLINE void mr_slist_init(mr_slist_t *entry) {
|
||||
entry->next = MR_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function adds an element to the list.
|
||||
*
|
||||
* @param head The list head.
|
||||
* @param entry The element to add.
|
||||
*
|
||||
* @note Adds to the end of the list.
|
||||
*/
|
||||
MR_INLINE void mr_slist_add(mr_slist_t *head, mr_slist_t *entry) {
|
||||
mr_slist_t *p;
|
||||
|
||||
p = head;
|
||||
while (!p->next) {
|
||||
p = p->next;
|
||||
}
|
||||
p->next = entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function inserts an element into the list.
|
||||
*
|
||||
* @param head The list head.
|
||||
* @param entry The element to insert.
|
||||
*
|
||||
* @note Inserts to the beginning of the list.
|
||||
*/
|
||||
MR_INLINE void mr_slist_insert(mr_slist_t *head, mr_slist_t *entry) {
|
||||
entry->next = head->next;
|
||||
head->next = entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function removes an element from the list.
|
||||
*
|
||||
* @param head The list head.
|
||||
* @param entry The element to remove.
|
||||
*/
|
||||
MR_INLINE void mr_slist_del(mr_slist_t *head, mr_slist_t *entry) {
|
||||
mr_slist_t *p;
|
||||
|
||||
p = head;
|
||||
while (!p->next) {
|
||||
if (p->next != entry) {
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
p->next = entry->next;
|
||||
entry->next = MR_NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function checks if the list is empty.
|
||||
*
|
||||
* @param head The list head.
|
||||
* @return MR_TRUE on empty, MR_FALSE otherwise.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_slist_is_empty(mr_slist_t *head) {
|
||||
return (!head->next) ? MR_TRUE : MR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This macro function iterates through the list.
|
||||
*
|
||||
* @param _pos The pointer to the element.
|
||||
* @param _head The list head.
|
||||
*/
|
||||
#define MR_SLIST_FOR_EACH(_pos, _head) \
|
||||
for ((_pos) = (_head)->next; (_pos) != MR_NULL; (_pos) = (_pos)->next)
|
||||
|
||||
/**
|
||||
* @brief This macro function iterates through the list in safe order.
|
||||
*
|
||||
* @param _pos The pointer to the element.
|
||||
* @param _n The pointer to the next element.
|
||||
* @param _head The list head.
|
||||
*/
|
||||
#define MR_SLIST_FOR_EACH_SAFE(_pos, _n, _head) \
|
||||
for ((_pos) = (_head)->next, (_n) = (_pos) ? (_pos)->next : MR_NULL; \
|
||||
(_pos) != MR_NULL; \
|
||||
(_pos) = (_n), (_n) = (_pos) ? (_pos)->next : MR_NULL)
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_SLIST_H__ */
|
||||
@@ -10,7 +10,7 @@
|
||||
#define __MR_SPINLOCK_H__
|
||||
|
||||
#include <arch/mr_hw_irq.h>
|
||||
#include <kernel/mr_atomic.h>
|
||||
#include <libc/mr_atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -38,30 +38,18 @@ MR_INLINE void mr_spinlock_init(mr_spinlock_t *lock) {
|
||||
mr_atomic_init(lock, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function tries to lock a spinlock.
|
||||
*
|
||||
* @param lock The spinlock to lock.
|
||||
* @return MR_TRUE on success, MR_FALSE on failure.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_spinlock_trylock(mr_spinlock_t *lock) {
|
||||
mr_spinlock_t unlock;
|
||||
|
||||
mr_spinlock_init(&unlock);
|
||||
if (!mr_atomic_compare_exchange(lock, &unlock, 1)) {
|
||||
return MR_FALSE;
|
||||
}
|
||||
return MR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function locks a spinlock.
|
||||
*
|
||||
* @param lock The spinlock to lock.
|
||||
*/
|
||||
MR_INLINE void mr_spinlock_lock(mr_spinlock_t *lock) {
|
||||
while (!mr_spinlock_trylock(lock)) {
|
||||
}
|
||||
mr_atomic_t unlock;
|
||||
|
||||
do {
|
||||
mr_atomic_init(&unlock, 0);
|
||||
unlock = mr_atomic_compare_exchange(lock, &unlock, 1);
|
||||
} while (!unlock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,11 +62,10 @@ MR_INLINE void mr_spinlock_unlock(mr_spinlock_t *lock) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function locks a spinlock with IRQs disabled and returns the
|
||||
* IRQ flags.
|
||||
* @brief This function locks a spinlock with interrupts disabled.
|
||||
*
|
||||
* @param lock The spinlock to lock.
|
||||
* @return The IRQ flags.
|
||||
* @return The interrupt mask.
|
||||
*/
|
||||
MR_INLINE int mr_spinlock_lock_irqsave(mr_spinlock_t *lock) {
|
||||
int mask;
|
||||
@@ -89,13 +76,13 @@ MR_INLINE int mr_spinlock_lock_irqsave(mr_spinlock_t *lock) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function unlocks a spinlock with IRQs disabled and restores the
|
||||
* IRQ mask.
|
||||
* @brief This function unlocks a spinlock with interrupts restored.
|
||||
*
|
||||
* @param lock The spinlock to unlock.
|
||||
* @param mask The IRQ mask.
|
||||
* @param mask The interrupt mask.
|
||||
*/
|
||||
MR_INLINE void mr_spinlock_unlock_irqrestore(mr_spinlock_t *lock, int mask) {
|
||||
MR_INLINE void mr_spinlock_unlock_irqrestore(mr_spinlock_t *lock, int mask)
|
||||
{
|
||||
mr_spinlock_unlock(lock);
|
||||
mr_hw_irq_restore(mask);
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_TIMER_H__
|
||||
#define __MR_TIMER_H__
|
||||
|
||||
#include <kernel/mr_clock.h>
|
||||
#include <kernel/mr_kobject.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Periodic definition */
|
||||
#define MR_TIMER_PERIODIC (1U << 31)
|
||||
|
||||
/* Timer type */
|
||||
typedef struct mr_timer {
|
||||
mr_kobject_t parent;
|
||||
mr_list_t list;
|
||||
mr_tick_t init_tick;
|
||||
mr_tick_t timeout_tick;
|
||||
mr_ptr_t entry;
|
||||
mr_ptr_t args;
|
||||
} mr_timer_t;
|
||||
|
||||
/**
|
||||
* @brief This function initialize a timer.
|
||||
*
|
||||
* @param timer The timer.
|
||||
* @param name The timer name.
|
||||
* @param entry The timer entry.
|
||||
* @param args The timer args.
|
||||
* @param tick The timer tick(period: 'tick | MR_TIMER_PERIODIC').
|
||||
* @returns 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_timer_init(mr_timer_t *timer, const char *name,
|
||||
void (*entry)(mr_timer_t *, void *), void *args,
|
||||
mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function create a timer.
|
||||
*
|
||||
* @param name The timer name.
|
||||
* @param entry The timer entry.
|
||||
* @param args The timer args.
|
||||
* @param tick The timer tick.
|
||||
* @return The timer on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_timer_t *mr_timer_create(const char *name,
|
||||
void (*entry)(mr_timer_t *, void *), void *args,
|
||||
mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function delete a timer.
|
||||
*
|
||||
* @param timer The timer.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_timer_del(mr_timer_t *timer);
|
||||
|
||||
/**
|
||||
* @brief This function start a timer.
|
||||
*
|
||||
* @param timer The timer.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_timer_start(mr_timer_t *timer);
|
||||
|
||||
/**
|
||||
* @brief This function stop a timer.
|
||||
*
|
||||
* @param timer The timer.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_timer_stop(mr_timer_t *timer);
|
||||
|
||||
/**
|
||||
* @brief This function set a timer tick.
|
||||
*
|
||||
* @param timer The timer.
|
||||
* @param tick The timer tick.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*
|
||||
* @note If the timer is running, it will be stopped.
|
||||
*/
|
||||
mr_err_t mr_timer_tick_set(mr_timer_t *timer, mr_tick_t tick);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_TIMER_H__ */
|
||||
@@ -69,25 +69,25 @@ menu "Libc"
|
||||
help
|
||||
The size of the heap in bytes.
|
||||
|
||||
# PRINTFK
|
||||
# STDIO
|
||||
choice
|
||||
prompt "Printfk"
|
||||
prompt "Stdio"
|
||||
default MR_USE_PRINTFK
|
||||
|
||||
config MR_USE_LIBC_PRINTFK
|
||||
bool "Standard libc printfk"
|
||||
config MR_USE_LIBC_STDIO
|
||||
bool "Standard libc stdio"
|
||||
help
|
||||
Use the standard libc printfk for printing.
|
||||
Use the standard libc stdio for I/O operations.
|
||||
|
||||
config MR_USE_3PARTY_PRINTFK
|
||||
bool "3rd party printfk"
|
||||
config MR_USE_3PARTY_STDIO
|
||||
bool "3rd party stdio"
|
||||
help
|
||||
Use a third-party printfk library for printing.
|
||||
Use a third-party stdio library for I/O operations.
|
||||
|
||||
config MR_USE_PRINTFK
|
||||
bool "Custom printfk"
|
||||
config MR_USE_STDIO
|
||||
bool "Custom stdio"
|
||||
help
|
||||
Use a custom printfk implementation for printing.
|
||||
Use a custom stdio implementation for I/O operations.
|
||||
endchoice
|
||||
|
||||
# STRING
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#elif defined(MR_USE_3PARTY_ASSERT)
|
||||
#include <3party/libc/mr_assert.h>
|
||||
#elif defined(MR_USE_ASSERT)
|
||||
#include <libc/mr_printfk.h>
|
||||
#include <libc/mr_kprintf.h>
|
||||
#endif /* defined(MR_USE_LIBC_ASSERT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -36,7 +36,7 @@ extern "C" {
|
||||
#define MR_ASSERT(_expr) \
|
||||
do { \
|
||||
if (!(_expr)) { \
|
||||
mr_printfk("%s:%d: %s\n", __FILE__, __LINE__, #_expr); \
|
||||
mr_kprintf("%s:%d: %s\n", __FILE__, __LINE__, #_expr); \
|
||||
while (1) { \
|
||||
} \
|
||||
} \
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __MR_ATOMIC_H__
|
||||
#define __MR_ATOMIC_H__
|
||||
|
||||
#include <kernel/mr_compiler.h>
|
||||
#include <libc/mr_compiler.h>
|
||||
#include <libc/mr_types.h>
|
||||
#if !defined(__CC_ARM) && !defined(__GNUC__) && !defined(__clang__)
|
||||
#include <arch/mr_hw_irq.h>
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_PRINTFK_H__
|
||||
#define __MR_PRINTFK_H__
|
||||
|
||||
#include <mr_config.h>
|
||||
#if defined(MR_USE_LIBC_PRINTFK)
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <libc/mr_types.h>
|
||||
#endif /* defined(MR_USE_LIBC_PRINTFK) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Printf
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Printf definition */
|
||||
#if defined(MR_USE_LIBC_PRINTFK)
|
||||
#define mr_printfk(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
|
||||
#define mr_snprintfk(_b, _s, _f, ...) snprintf(_b, _s, _f, ##__VA_ARGS__)
|
||||
#else
|
||||
/**
|
||||
* @brief This function prints a formatted string.
|
||||
*
|
||||
* @param fmt The format string.
|
||||
* @param ... The arguments.
|
||||
* @return The number of characters printed.
|
||||
*/
|
||||
int mr_printfk(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief This function prints a formatted string.
|
||||
*
|
||||
* @param buf The buffer.
|
||||
* @param size The size of the buffer.
|
||||
* @param fmt The format string.
|
||||
* @param ... The arguments.
|
||||
* @return The number of characters printed.
|
||||
*/
|
||||
int mr_snprintfk(char *buf, mr_size_t size, const char *fmt, ...);
|
||||
#endif /* defined(MR_USE_LIBC_PRINTFK) */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_PRINTFK_H__ */
|
||||
42
include/libc/mr_stdio.h
Normal file
42
include/libc/mr_stdio.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_STDIO_H__
|
||||
#define __MR_STDIO_H__
|
||||
|
||||
#include <mr_config.h>
|
||||
#if defined(MR_USE_LIBC_STDIO)
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <libc/mr_types.h>
|
||||
#endif /* defined(MR_USE_LIBC_STDIO) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Stdio
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Stdio definition */
|
||||
#if defined(MR_USE_LIBC_STDIO)
|
||||
#define mr_vprintf(_f, _a) vprintf(_f, _a)
|
||||
#define mr_vsnprintf(_b, _s, _f, _a) vsnprintf(_b, _s, _f, _a)
|
||||
#else
|
||||
|
||||
#endif /* defined(MR_USE_LIBC_STDIO) */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_STDIO_H__ */
|
||||
@@ -5,6 +5,12 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
//#define MR_USE_THREAD
|
||||
#define MR_USE_LIBC_MALLOC
|
||||
#define MR_USE_ASSERT
|
||||
#define MR_USE_LIBC_ASSERT
|
||||
#define MR_USE_LIBC_STDIO
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_atomic.h>
|
||||
#include <kernel/mr_clock.h>
|
||||
#include <kernel/mr_hooks.h>
|
||||
|
||||
static mr_atomic_t kclock;
|
||||
#if !defined(MR_CFG_CLOCK_HOOK_SIZE)
|
||||
#define MR_CFG_CLOCK_HOOK_SIZE (4)
|
||||
#endif /* !defined(MR_CFG_CLOCK_HOOK_SIZE) */
|
||||
#if defined(MR_USE_THREAD) && (MR_CFG_CLOCK_HOOK_SIZE < 2)
|
||||
#error "If use thread, clock hook size must >= 2"
|
||||
#endif /* defined(MR_USE_THREAD) && (MR_CFG_CLOCK_HOOK_SIZE < 2) */
|
||||
static mr_ptr_t khook[MR_CFG_CLOCK_HOOK_SIZE];
|
||||
static mr_hooks_t khooks = MR_HOOKS_INIT(khook, MR_CFG_CLOCK_HOOK_SIZE);
|
||||
|
||||
MR_INLINE void clock_hooks_call(void) {
|
||||
void (*hook)(void);
|
||||
mr_size_t i;
|
||||
|
||||
/* Each hooks */
|
||||
MR_HOOKS_EACH(i, &khooks, hook) {
|
||||
if (!hook) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Call hook */
|
||||
hook();
|
||||
}
|
||||
}
|
||||
|
||||
void mr_clock_increase(mr_clock_t clock) {
|
||||
/* Clock increase */
|
||||
mr_atomic_fetch_add(&kclock, (mr_atomic_t)clock);
|
||||
|
||||
/* Call hooks */
|
||||
clock_hooks_call();
|
||||
}
|
||||
|
||||
mr_clock_t mr_clock_get(void) {
|
||||
/* Get kclock */
|
||||
return (mr_clock_t)mr_atomic_load(&kclock);
|
||||
}
|
||||
|
||||
void mr_clock_set(mr_clock_t clock) {
|
||||
/* Set kclock */
|
||||
mr_atomic_store(&kclock, (mr_atomic_t)clock);
|
||||
}
|
||||
|
||||
int mr_clock_hook_add(int index, void (*hook)(void)) {
|
||||
/* Add hook */
|
||||
return mr_hooks_add(&khooks, index, hook);
|
||||
}
|
||||
|
||||
void mr_clock_hook_del(int index) {
|
||||
/* Delete hook */
|
||||
mr_hooks_del(&khooks, index);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_hooks.h>
|
||||
|
||||
void mr_hooks_init(mr_hooks_t *hooks, mr_ptr_t *hook, mr_size_t size) {
|
||||
/* Check arguments */
|
||||
if ((!hooks) || (!hook) || (!size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize hooks */
|
||||
mr_spinlock_init(&hooks->lock);
|
||||
hooks->hook = hook;
|
||||
hooks->size = size;
|
||||
}
|
||||
|
||||
int mr_hooks_add(mr_hooks_t *hooks, int index, mr_ptr_t hook) {
|
||||
mr_size_t i;
|
||||
int ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!hooks) || (index < -1) || (index >= (int)hooks->size)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Lock hooks */
|
||||
mr_spinlock_lock(&hooks->lock);
|
||||
|
||||
/* Add hooks */
|
||||
if (index >= 0) {
|
||||
hooks->hook[index] = hook;
|
||||
ret = index;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Allocate hooks */
|
||||
for (i = 0; i < hooks->size; i++) {
|
||||
if (hooks->hook[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Allocate success */
|
||||
hooks->hook[i] = hook;
|
||||
ret = (int)i;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Allocate fail */
|
||||
ret = -MR_ENOMEM;
|
||||
|
||||
_exit:
|
||||
/* Unlock hooks */
|
||||
mr_spinlock_unlock(&hooks->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mr_hooks_del(mr_hooks_t *hooks, int index) {
|
||||
/* Check arguments */
|
||||
if ((!hooks) || (index < 0) || (index >= (int)hooks->size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Lock hooks */
|
||||
mr_spinlock_lock(&hooks->lock);
|
||||
|
||||
/* Delete hooks */
|
||||
hooks->hook[index] = MR_NULL;
|
||||
|
||||
/* Unlock hooks */
|
||||
mr_spinlock_unlock(&hooks->lock);
|
||||
}
|
||||
@@ -30,7 +30,7 @@ void mr_autoinit_kernel(void) {
|
||||
/* Run initcalls(kernel) */
|
||||
for (ic = &__mr_initcall_kernel_start; ic <= &__mr_initcall_kernel_end;
|
||||
ic++) {
|
||||
ic->fn();
|
||||
ic->entry();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,6 @@ void mr_autoinit(void) {
|
||||
/* Run initcalls(user) */
|
||||
for (ic = &__mr_initcall_user_start; ic <= &__mr_initcall_user_end;
|
||||
ic++) {
|
||||
ic->fn();
|
||||
ic->entry();
|
||||
}
|
||||
}
|
||||
|
||||
54
kernel/kclock.c
Normal file
54
kernel/kclock.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_kclock.h>
|
||||
#include <kernel/mr_khook.h>
|
||||
#include <libc/mr_atomic.h>
|
||||
|
||||
static mr_atomic_t kclock;
|
||||
#if !defined(MR_CFG_KCLOCK_HOOK_SIZE)
|
||||
#define MR_CFG_KCLOCK_HOOK_SIZE (4)
|
||||
#endif /* !defined(MR_CFG_KCLOCK_HOOK_SIZE) */
|
||||
#if defined(MR_USE_THREAD) && (MR_CFG_KCLOCK_HOOK_SIZE < 2)
|
||||
#error "If use thread, clock hook size must >= 2"
|
||||
#endif /* defined(MR_USE_THREAD) && (MR_CFG_KCLOCK_HOOK_SIZE < 2) */
|
||||
static mr_ptr_t kentry[MR_CFG_KCLOCK_HOOK_SIZE];
|
||||
static mr_khook_t khook = MR_KHOOK_INIT(kentry, MR_CFG_KCLOCK_HOOK_SIZE);
|
||||
|
||||
MR_INLINE void kclock_hook(void) {
|
||||
void (*entry)(void);
|
||||
mr_size_t i;
|
||||
|
||||
/* Each hooks */
|
||||
MR_KHOOK_EACH(i, entry, &khook) {
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Call entry */
|
||||
entry();
|
||||
}
|
||||
}
|
||||
|
||||
void mr_kclock_increase(mr_tick_t tick) {
|
||||
/* Clock increase */
|
||||
mr_atomic_fetch_add(&kclock, (mr_atomic_t)tick);
|
||||
|
||||
/* Call hooks */
|
||||
kclock_hook();
|
||||
}
|
||||
|
||||
mr_tick_t mr_kclock_tick(void) {
|
||||
/* Get kclock */
|
||||
return (mr_tick_t)mr_atomic_load(&kclock);
|
||||
}
|
||||
|
||||
mr_err_t mr_kclock_hook_add(void (*entry)(void)) {
|
||||
/* Add entry to khook */
|
||||
return mr_khook_add(&khook, entry);
|
||||
}
|
||||
100
kernel/kfifo.c
Normal file
100
kernel/kfifo.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @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) {
|
||||
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, 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(buf + s, kfifo->buf, size - s);
|
||||
return size;
|
||||
}
|
||||
49
kernel/khook.c
Normal file
49
kernel/khook.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_khook.h>
|
||||
|
||||
void mr_khook_init(mr_khook_t *khook, mr_ptr_t *entry, mr_size_t size) {
|
||||
/* Check arguments */
|
||||
if ((!khook) || ((!entry) && (size == 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize khook */
|
||||
mr_spinlock_init(&khook->lock);
|
||||
khook->entry = entry;
|
||||
khook->size = size;
|
||||
khook->next = 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_khook_add(mr_khook_t *khook, mr_ptr_t entry) {
|
||||
mr_err_t ret;
|
||||
mr_size_t i;
|
||||
int mask;
|
||||
|
||||
/* Check arguments */
|
||||
if (!khook) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Lock khook */
|
||||
mask = mr_spinlock_lock_irqsave(&khook->lock);
|
||||
|
||||
/* Add entry to khook */
|
||||
if (khook->next < khook->size) {
|
||||
khook->entry[khook->next++] = entry;
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Out of space */
|
||||
ret = -MR_ENOMEM;
|
||||
}
|
||||
|
||||
/* Unlock khook */
|
||||
mr_spinlock_unlock_irqrestore(&khook->lock, mask);
|
||||
return ret;
|
||||
}
|
||||
202
kernel/kmap.c
Normal file
202
kernel/kmap.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_kmap.h>
|
||||
#include <libc/mr_compiler.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
|
||||
mr_err_t mr_kmap_init(mr_kmap_t *kmap, mr_size_t size, mr_f32_t load_factor) {
|
||||
/* Check arguments */
|
||||
if ((size == 0) || (load_factor <= 0.0f) || (load_factor > 1.0f)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize kmap */
|
||||
kmap->b = mr_calloc(size, sizeof(mr_knode_t));
|
||||
if (!kmap->b) {
|
||||
return -MR_ENOMEM;
|
||||
}
|
||||
kmap->size = size;
|
||||
kmap->count = 0;
|
||||
kmap->load_factor = load_factor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kmap_resize(mr_kmap_t *kmap, mr_size_t new_size) {
|
||||
mr_knode_t *node, *prev;
|
||||
mr_knode_t **new_b;
|
||||
mr_size_t index, i;
|
||||
|
||||
if (new_size == kmap->size) {
|
||||
/* No need to resize */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate new bucket */
|
||||
if (new_size > 0) {
|
||||
new_b = mr_calloc(new_size, sizeof(mr_knode_t));
|
||||
if (!new_b) {
|
||||
return -MR_ENOMEM;
|
||||
}
|
||||
|
||||
/* Rehash */
|
||||
for (i = 0; i < kmap->size; i++) {
|
||||
node = kmap->b[i];
|
||||
while (node) {
|
||||
prev = node;
|
||||
node = node->next;
|
||||
index = prev->key % new_size;
|
||||
prev->next = new_b[index];
|
||||
new_b[index] = prev;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
new_b = MR_NULL;
|
||||
}
|
||||
|
||||
/* Update kmap */
|
||||
mr_free(kmap->b);
|
||||
kmap->b = new_b;
|
||||
kmap->size = new_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_kmap_add(mr_kmap_t *kmap, mr_uint32_t key, void *value) {
|
||||
mr_knode_t *node;
|
||||
mr_size_t index;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((kmap->size == 0) || (!value)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Check load factor */
|
||||
if (((mr_f32_t)kmap->count / (mr_f32_t)kmap->size) >= kmap->load_factor) {
|
||||
/* Resize kmap */
|
||||
ret = kmap_resize(kmap, kmap->size * 2);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update existing node */
|
||||
index = key % kmap->size;
|
||||
node = kmap->b[index];
|
||||
while (node) {
|
||||
if (node->key != key) {
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Update value */
|
||||
node->value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert new node */
|
||||
node = mr_malloc(sizeof(mr_knode_t));
|
||||
if (!node) {
|
||||
return -MR_ENOMEM;
|
||||
}
|
||||
node->key = key;
|
||||
node->value = value;
|
||||
node->next = kmap->b[index];
|
||||
kmap->b[index] = node;
|
||||
kmap->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *mr_kmap_del(mr_kmap_t *kmap, mr_uint32_t key) {
|
||||
mr_knode_t *node, *prev;
|
||||
mr_size_t index;
|
||||
void *value;
|
||||
|
||||
/* Check arguments */
|
||||
if (kmap->size == 0) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Remove node */
|
||||
index = key % kmap->size;
|
||||
node = kmap->b[index];
|
||||
prev = MR_NULL;
|
||||
while (node) {
|
||||
if (node->key != key) {
|
||||
prev = node;
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
if (!prev) {
|
||||
kmap->b[index] = node->next;
|
||||
} else {
|
||||
prev->next = node->next;
|
||||
}
|
||||
value = node->value;
|
||||
mr_free(node);
|
||||
kmap->count--;
|
||||
|
||||
/* Check shrink factor */
|
||||
if (((((mr_f32_t)kmap->size * kmap->load_factor) / 4.0f)
|
||||
> (mr_f32_t)kmap->count)) {
|
||||
/* Resize kmap */
|
||||
kmap_resize(kmap, kmap->size / 2);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
void *mr_kmap_value(mr_kmap_t *kmap, mr_uint32_t key) {
|
||||
mr_knode_t *node;
|
||||
mr_size_t index;
|
||||
|
||||
/* Check arguments */
|
||||
if (kmap->size == 0) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Find node */
|
||||
index = key % kmap->size;
|
||||
node = kmap->b[index];
|
||||
while (node) {
|
||||
if (node->key != key) {
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
return node->value;
|
||||
}
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
void mr_kmap_clear(mr_kmap_t *kmap) {
|
||||
mr_knode_t *node, *prev;
|
||||
mr_size_t i;
|
||||
|
||||
/* Clear kmap */
|
||||
for (i = 0; i < kmap->size; i++) {
|
||||
node = kmap->b[i];
|
||||
while (node) {
|
||||
prev = node;
|
||||
node = node->next;
|
||||
mr_free(prev);
|
||||
}
|
||||
kmap->b[i] = MR_NULL;
|
||||
}
|
||||
kmap->count = 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_kmap_shrink(mr_kmap_t *kmap, mr_size_t size) {
|
||||
/* Check arguments */
|
||||
if (size < kmap->count) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Resize kmap */
|
||||
return kmap_resize(kmap, size);
|
||||
}
|
||||
221
kernel/kobject.c
221
kernel/kobject.c
@@ -7,8 +7,9 @@
|
||||
*/
|
||||
|
||||
#include <kernel/mr_kobject.h>
|
||||
#include <kernel/mr_spinlock.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
#include <libc/mr_printfk.h>
|
||||
#include <libc/mr_stdio.h>
|
||||
#include <libc/mr_string.h>
|
||||
|
||||
/* Last-word definition */
|
||||
@@ -16,7 +17,8 @@
|
||||
#define LWORD_DOT2 (0x2e2e)
|
||||
|
||||
/* Root kset */
|
||||
static mr_kset_t kroot = MR_KSET_INIT(kroot, MR_NULL);
|
||||
static mr_spinlock_t klock = MR_SPINLOCK_INIT();
|
||||
static mr_kset_t kroot = MR_KSET_INIT(&kroot, MR_NULL);
|
||||
|
||||
void mr_ktype_init(mr_ktype_t *type, void (*release)(mr_kobject_t *)) {
|
||||
/* Check arguments */
|
||||
@@ -44,22 +46,18 @@ void mr_kobject_init(mr_kobject_t *kobj, mr_ktype_t *type) {
|
||||
kname_init(&kobj->name);
|
||||
kobj->parent = kobj;
|
||||
kobj->type = type;
|
||||
mr_lockref_init(&kobj->ref);
|
||||
mr_list_init(&kobj->entry);
|
||||
mr_list_init(&kobj->list);
|
||||
mr_klist_init(&kobj->entry);
|
||||
mr_klist_init(&kobj->list);
|
||||
mr_kref_init(&kobj->ref);
|
||||
kobj->magic = MR_KOBJECT_MAGIC;
|
||||
}
|
||||
|
||||
MR_INLINE mr_bool_t kobject_is_added(mr_kobject_t *kobj) {
|
||||
return !mr_list_is_empty(&kobj->entry);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t path_alloc_varg(const char *fmt, mr_va_list args,
|
||||
const char **path) {
|
||||
int path_len;
|
||||
|
||||
/* Get path length */
|
||||
path_len = mr_snprintfk(MR_NULL, 0, fmt, args);
|
||||
path_len = mr_vsnprintf(MR_NULL, 0, fmt, args);
|
||||
if (path_len < 0) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
@@ -71,7 +69,7 @@ MR_INLINE mr_err_t path_alloc_varg(const char *fmt, mr_va_list args,
|
||||
}
|
||||
|
||||
/* Format path */
|
||||
mr_snprintfk((char *)*path, path_len + 1, fmt, args);
|
||||
mr_vsnprintf((char *)*path, path_len + 1, fmt, args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -102,10 +100,11 @@ MR_INLINE mr_bool_t kname_match(mr_kname_t *kn1, mr_kname_t *kn2) {
|
||||
MR_INLINE mr_kobject_t *kobject_lookup_kname(mr_kobject_t *last,
|
||||
mr_kname_t *kname) {
|
||||
mr_kobject_t *kobj;
|
||||
mr_list_t *l;
|
||||
mr_klist_t *l;
|
||||
|
||||
MR_LIST_FOR_EACH(l, &last->list) {
|
||||
kobj = MR_LIST_ENTRY(l, mr_kobject_t, entry);
|
||||
/* For each kobject */
|
||||
MR_KLIST_FOR_EACH(l, &last->list) {
|
||||
kobj = MR_KLIST_ENTRY(l, mr_kobject_t, entry);
|
||||
|
||||
/* Match object name */
|
||||
if (!kname_match(&kobj->name, kname)) {
|
||||
@@ -115,6 +114,8 @@ MR_INLINE mr_kobject_t *kobject_lookup_kname(mr_kobject_t *last,
|
||||
/* Found */
|
||||
return kobj;
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
@@ -154,19 +155,15 @@ MR_INLINE mr_kobject_t *kobject_lookup_path(mr_kobject_t **last,
|
||||
default: {
|
||||
/* Handle 'other' */
|
||||
kobj = kobject_lookup_kname(*last, &kname);
|
||||
if (!kobj) {
|
||||
/* Not found */
|
||||
return MR_NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get found kobject */
|
||||
kobj = mr_kobject_get(kobj);
|
||||
if (!kobj) {
|
||||
/* Not found */
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Update last */
|
||||
mr_kobject_put(*last);
|
||||
*last = kobj;
|
||||
}
|
||||
return *last;
|
||||
@@ -207,56 +204,56 @@ MR_INLINE void path_free(const char *path) {
|
||||
mr_free((char *)path);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kobject_add_varg(mr_kobject_t *kobj, mr_kobject_t *parent,
|
||||
const char *fmt, mr_va_list args) {
|
||||
const char *path, *path2;
|
||||
MR_INLINE mr_err_t kobject_add(mr_kobject_t *kobj, mr_kobject_t **parent,
|
||||
const char *path) {
|
||||
mr_err_t ret;
|
||||
|
||||
/* Already added */
|
||||
if (kobject_is_added(kobj)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get parent */
|
||||
parent = mr_kobject_get(parent);
|
||||
if (!parent) {
|
||||
ret = -MR_EINVAL;
|
||||
goto _exit_nf;
|
||||
}
|
||||
|
||||
/* Allocate path */
|
||||
ret = path_alloc_varg(fmt, args, &path);
|
||||
if (ret != 0) {
|
||||
goto _exit_nf;
|
||||
} else {
|
||||
/* Save path for free */
|
||||
path2 = path;
|
||||
}
|
||||
|
||||
/* Lookup path in parent */
|
||||
if (kobject_lookup_path(&parent, &path, parent)) {
|
||||
ret = -MR_EEXIST;
|
||||
goto _exit;
|
||||
if (kobject_lookup_path(parent, &path, *parent)) {
|
||||
return -MR_EEXIST;
|
||||
}
|
||||
|
||||
/* Allocate name */
|
||||
ret = kobject_name_alloc(kobj, path);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add kobject to parent */
|
||||
kobj->parent = mr_kobject_get(*parent);
|
||||
mr_klist_add(&(*parent)->list, &kobj->entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kobject_add_varg(mr_kobject_t *kobj, mr_kobject_t *parent,
|
||||
const char *fmt, mr_va_list args) {
|
||||
const char *path;
|
||||
mr_err_t ret;
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Already added */
|
||||
if (!mr_klist_is_empty(&kobj->entry)) {
|
||||
ret = -MR_EBUSY;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Allocate path */
|
||||
ret = path_alloc_varg(fmt, args, &path);
|
||||
if (ret != 0) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Add kobject to parent */
|
||||
kobj->parent = mr_kobject_get(parent);
|
||||
mr_lockref_lock(&parent->ref);
|
||||
mr_list_add(&parent->list, &kobj->entry);
|
||||
mr_lockref_unlock(&parent->ref);
|
||||
ret = kobject_add(kobj, &parent, path);
|
||||
|
||||
_exit:
|
||||
/* Free path */
|
||||
path_free(path2);
|
||||
_exit_nf:
|
||||
/* Put parent */
|
||||
mr_kobject_put(parent);
|
||||
path_free(path);
|
||||
_exit:
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -266,44 +263,34 @@ mr_err_t mr_kobject_add(mr_kobject_t *kobj, mr_kobject_t *parent,
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!kobj) || (!MR_KOBJECT_IS_INITED(kobj)) || (!parent) || (!fmt)) {
|
||||
if ((!kobj) || (!MR_KOBJECT_IS_INITED(kobj)) || (!parent)
|
||||
|| (!MR_KOBJECT_IS_INITED(parent)) || (!fmt)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Add kobject to kroot */
|
||||
/* Add kobject to parent */
|
||||
mr_va_start(args, fmt);
|
||||
mr_lockref_lock(&kobj->ref);
|
||||
ret = kobject_add_varg(kobj, parent, fmt, args);
|
||||
mr_lockref_unlock(&kobj->ref);
|
||||
mr_va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MR_INLINE mr_bool_t kobject_is_deleted(mr_kobject_t *kobj) {
|
||||
return kobj->parent == kobj;
|
||||
}
|
||||
|
||||
MR_INLINE void kobject_del(mr_kobject_t *kobj) {
|
||||
mr_kobject_t *parent;
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Already deleted */
|
||||
if (kobject_is_deleted(kobj)) {
|
||||
return;
|
||||
if (mr_klist_is_empty(&kobj->entry)) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Get parent */
|
||||
parent = mr_kobject_get(kobj->parent);
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove from parent */
|
||||
mr_lockref_lock(&parent->ref);
|
||||
mr_list_del(&kobj->entry);
|
||||
mr_lockref_unlock(&parent->ref);
|
||||
|
||||
/* Put parent */
|
||||
mr_kobject_put(parent);
|
||||
/* Remove kobject from parent */
|
||||
mr_klist_del(&kobj->entry);
|
||||
_exit:
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
void mr_kobject_del(mr_kobject_t *kobj) {
|
||||
@@ -313,14 +300,59 @@ void mr_kobject_del(mr_kobject_t *kobj) {
|
||||
}
|
||||
|
||||
/* Delete kobject */
|
||||
mr_lockref_lock(&kobj->ref);
|
||||
kobject_del(kobj);
|
||||
mr_lockref_unlock(&kobj->ref);
|
||||
|
||||
/* Put kobject */
|
||||
mr_kobject_put(kobj);
|
||||
}
|
||||
|
||||
MR_INLINE mr_kobject_t *kobject_lookup_varg(mr_kobject_t *parent,
|
||||
const char *fmt, mr_va_list args) {
|
||||
const char *path, *path2;
|
||||
mr_kobject_t *kobj;
|
||||
mr_err_t ret;
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Allocate path */
|
||||
ret = path_alloc_varg(fmt, args, &path);
|
||||
if (ret != 0) {
|
||||
kobj = MR_NULL;
|
||||
goto _exit;
|
||||
} else {
|
||||
/* Save path for free */
|
||||
path2 = path;
|
||||
}
|
||||
|
||||
/* Lookup kobject for path */
|
||||
kobj = kobject_lookup_path(&parent, &path, parent);
|
||||
|
||||
/* Free path */
|
||||
path_free(path2);
|
||||
_exit:
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
return kobj;
|
||||
}
|
||||
|
||||
mr_kobject_t *mr_kobject_lookup(mr_kobject_t *parent, const char *fmt, ...) {
|
||||
mr_kobject_t *kobj;
|
||||
mr_va_list args;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!parent) || (!MR_KOBJECT_IS_INITED(parent)) || (!fmt)) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Lookup kobject from parent */
|
||||
mr_va_start(args, fmt);
|
||||
kobj = kobject_lookup_varg(parent, fmt, args);
|
||||
mr_va_end(args);
|
||||
return kobj;
|
||||
}
|
||||
|
||||
mr_kobject_t *mr_kobject_get(mr_kobject_t *kobj) {
|
||||
/* Check arguments */
|
||||
if ((!kobj) || (!MR_KOBJECT_IS_INITED(kobj))) {
|
||||
@@ -328,7 +360,7 @@ mr_kobject_t *mr_kobject_get(mr_kobject_t *kobj) {
|
||||
}
|
||||
|
||||
/* Get kobject */
|
||||
mr_lockref_get(&kobj->ref);
|
||||
mr_kref_get(&kobj->ref);
|
||||
return kobj;
|
||||
}
|
||||
|
||||
@@ -342,7 +374,7 @@ MR_INLINE void kobject_release(mr_kobject_t *kobj) {
|
||||
}
|
||||
}
|
||||
|
||||
MR_INLINE void kobject_release_ref(mr_lockref_t *ref) {
|
||||
MR_INLINE void kobject_release_ref(mr_kref_t *ref) {
|
||||
mr_kobject_t *kobj, *parent;
|
||||
const char *name;
|
||||
|
||||
@@ -377,25 +409,20 @@ void mr_kobject_put(mr_kobject_t *kobj) {
|
||||
}
|
||||
|
||||
/* Put kobject */
|
||||
mr_lockref_put(&kobj->ref, kobject_release_ref);
|
||||
mr_kref_put(&kobj->ref, kobject_release_ref);
|
||||
}
|
||||
|
||||
void mr_kset_init(mr_kset_t *kset, mr_ktype_t *type) {
|
||||
/* Check arguments */
|
||||
if (!kset) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init kset */
|
||||
mr_kobject_init((mr_kobject_t *)kset, type);
|
||||
}
|
||||
|
||||
mr_err_t mr_kset_register(mr_kset_t *kset, const char *name) {
|
||||
/* Check arguments */
|
||||
if ((!kset) || (!name)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Add kset to kroot */
|
||||
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);
|
||||
}
|
||||
|
||||
20
kernel/kprintf.c
Normal file
20
kernel/kprintf.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_kprintf.h>
|
||||
#include <libc/mr_types.h>
|
||||
|
||||
int mr_kprintf(const char *fmt, ...) {
|
||||
mr_va_list args;
|
||||
int ret;
|
||||
|
||||
mr_va_start(args, fmt);
|
||||
ret = mr_vprintf(fmt, args);
|
||||
mr_va_end(args);
|
||||
return ret;
|
||||
}
|
||||
291
kernel/ktimer.c
Normal file
291
kernel/ktimer.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_initcall.h>
|
||||
#include <kernel/mr_ktimer.h>
|
||||
#include <kernel/mr_spinlock.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
|
||||
static mr_ktype_t ktype1, ktype2;
|
||||
static mr_kset_t kroot = MR_KSET_INIT(&kroot, MR_NULL);
|
||||
static mr_klist_t klist = MR_KLIST_INIT(&klist);
|
||||
static mr_spinlock_t klock = MR_SPINLOCK_INIT();
|
||||
|
||||
MR_INLINE void ktimer_init(mr_ktimer_t *ktimer, mr_ptr_t entry, void *args,
|
||||
mr_tick_t tick) {
|
||||
/* Init ktimer */
|
||||
mr_klist_init(&ktimer->list);
|
||||
ktimer->init_tick = tick;
|
||||
ktimer->timeout_tick = 0;
|
||||
ktimer->entry = entry;
|
||||
ktimer->args = args;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t ktimer_init_add(mr_ktimer_t *ktimer, mr_ktype_t *ktype,
|
||||
const char *name, mr_ptr_t entry, void *args,
|
||||
mr_tick_t tick) {
|
||||
/* Init ktimer */
|
||||
ktimer_init(ktimer, entry, args, tick);
|
||||
|
||||
/* Init kobject */
|
||||
mr_kobject_init((mr_kobject_t *)ktimer, ktype);
|
||||
|
||||
/* Add kobject to kroot */
|
||||
return mr_kobject_add((mr_kobject_t *)ktimer, (mr_kobject_t *)&kroot, name);
|
||||
}
|
||||
|
||||
mr_err_t mr_ktimer_init(mr_ktimer_t *ktimer, const char *name,
|
||||
void (*entry)(mr_ktimer_t *, void *), void *args,
|
||||
mr_tick_t tick) {
|
||||
/* Check arguments */
|
||||
if ((!ktimer) || (MR_KOBJECT_IS_INITED(ktimer)) || (!name) || (!entry)
|
||||
|| (tick == 0)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Init and add ktimer */
|
||||
return ktimer_init_add(ktimer, &ktype1, name, (mr_ptr_t)entry, args, tick);
|
||||
}
|
||||
|
||||
mr_ktimer_t *mr_ktimer_create(const char *name,
|
||||
void (*entry)(mr_ktimer_t *, void *), void *args,
|
||||
mr_tick_t tick) {
|
||||
mr_ktimer_t *ktimer;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!name) || (!entry) || (tick == 0)) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Create ktimer */
|
||||
ktimer = mr_malloc(sizeof(mr_ktimer_t));
|
||||
if (!ktimer) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Init and add ktimer */
|
||||
ret = ktimer_init_add(ktimer, &ktype2, name, (mr_ptr_t)entry, args, tick);
|
||||
if (ret != 0) {
|
||||
/* Free ktimer */
|
||||
mr_free(ktimer);
|
||||
return MR_NULL;
|
||||
}
|
||||
return ktimer;
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_del(mr_ktimer_t *ktimer) {
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Already deleted */
|
||||
if (mr_klist_is_empty(&ktimer->list)) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Remove ktimer from ktimer list */
|
||||
mr_klist_del(&ktimer->list);
|
||||
_exit:
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_ktimer_del(mr_ktimer_t *ktimer) {
|
||||
/* Check arguments */
|
||||
if ((!ktimer) || (!MR_KOBJECT_IS_INITED(ktimer))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete ktimer */
|
||||
ktimer_del(ktimer);
|
||||
|
||||
/* Delete kobject */
|
||||
mr_kobject_del((mr_kobject_t *)ktimer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_insert(mr_ktimer_t *ktimer) {
|
||||
mr_tick_t tick;
|
||||
mr_ktimer_t *t;
|
||||
mr_klist_t *l;
|
||||
|
||||
/* Set timeout tick */
|
||||
tick = ktimer->init_tick & ~MR_KTIMER_PERIODIC;
|
||||
ktimer->timeout_tick = mr_kclock_tick() + tick;
|
||||
|
||||
/* Insert ktimer into ktimer list */
|
||||
MR_KLIST_FOR_EACH(l, &klist) {
|
||||
t = MR_KLIST_ENTRY(l, mr_ktimer_t, list);
|
||||
if ((ktimer->timeout_tick - t->timeout_tick) < (MR_TICK_MAX / 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Move ktimer into position */
|
||||
mr_klist_move(&ktimer->list, &t->list);
|
||||
return;
|
||||
}
|
||||
|
||||
/* It is the last ktimer */
|
||||
mr_klist_move(&ktimer->list, &klist);
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_start(mr_ktimer_t *ktimer) {
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Insert ktimer into ktimer list */
|
||||
ktimer_insert(ktimer);
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_ktimer_start(mr_ktimer_t *ktimer) {
|
||||
/* Check arguments */
|
||||
if ((!ktimer) || (!MR_KOBJECT_IS_INITED(ktimer))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Start ktimer */
|
||||
ktimer_start(ktimer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_ktimer_stop(mr_ktimer_t *ktimer) {
|
||||
/* Check arguments */
|
||||
if ((!ktimer) || (!MR_KOBJECT_IS_INITED(ktimer))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete ktimer */
|
||||
ktimer_del(ktimer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_tick_set(mr_ktimer_t *ktimer, mr_tick_t tick) {
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Set init tick */
|
||||
ktimer->init_tick = tick;
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_ktimer_tick_set(mr_ktimer_t *ktimer, mr_tick_t tick) {
|
||||
/* Check arguments */
|
||||
if ((!ktimer) || (!MR_KOBJECT_IS_INITED(ktimer)) || (tick == 0)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete ktimer */
|
||||
ktimer_del(ktimer);
|
||||
|
||||
/* Set ktimer tick */
|
||||
ktimer_tick_set(ktimer, tick);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_release1_kobj(mr_kobject_t *kobj) {
|
||||
mr_ktimer_t *ktimer;
|
||||
|
||||
/* Get ktimer */
|
||||
ktimer = MR_CONTAINER_OF(kobj, mr_ktimer_t, parent);
|
||||
|
||||
/* Delete ktimer */
|
||||
ktimer_del(ktimer);
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_release2_kobj(mr_kobject_t *kobj) {
|
||||
mr_ktimer_t *ktimer;
|
||||
|
||||
/* Get ktimer */
|
||||
ktimer = MR_CONTAINER_OF(kobj, mr_ktimer_t, parent);
|
||||
|
||||
/* Delete ktimer */
|
||||
ktimer_del(ktimer);
|
||||
|
||||
/* Free ktimer */
|
||||
mr_free(ktimer);
|
||||
}
|
||||
|
||||
MR_INLINE void ktimer_timeout_check(void) {
|
||||
mr_ktimer_t *ktimer;
|
||||
mr_klist_t list;
|
||||
mr_tick_t tick;
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Check timeout ktimer */
|
||||
while (!mr_klist_is_empty(&klist)) {
|
||||
ktimer = MR_KLIST_ENTRY(klist.next, mr_ktimer_t, list);
|
||||
|
||||
/* Get current tick */
|
||||
tick = mr_kclock_tick();
|
||||
if ((tick - ktimer->timeout_tick) >= (MR_TICK_MAX / 2)) {
|
||||
/* There will be no timeout ktimer after that */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move ktimer into operation list */
|
||||
mr_klist_init(&list);
|
||||
mr_klist_move(&ktimer->list, &list);
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock(&klock);
|
||||
|
||||
/* Call ktimer entry */
|
||||
((void (*)(mr_ktimer_t *, void *))ktimer->entry)(ktimer, ktimer->args);
|
||||
|
||||
/* Lock */
|
||||
mr_spinlock_lock(&klock);
|
||||
|
||||
/* Check that the ktimer has not been moved */
|
||||
if (mr_klist_is_empty(&list)) {
|
||||
/* Timer is no longer yours to operate */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tick is periodic */
|
||||
if (ktimer->init_tick & MR_KTIMER_PERIODIC) {
|
||||
/* Restart ktimer */
|
||||
ktimer_insert(ktimer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
MR_INLINE void mr_ktimer_kset_init(void) {
|
||||
mr_err_t ret;
|
||||
|
||||
/* Register kset */
|
||||
ret = mr_kset_register(&kroot, "timer");
|
||||
if (ret != 0) {
|
||||
/* It won't entry the kclock, so it won't start */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init ktype */
|
||||
mr_ktype_init(&ktype1, ktimer_release1_kobj);
|
||||
mr_ktype_init(&ktype2, ktimer_release2_kobj);
|
||||
|
||||
/* Add kclock entry */
|
||||
mr_kclock_hook_add(ktimer_timeout_check);
|
||||
}
|
||||
MR_INIT_EXPORT(mr_ktimer_kset_init, MR_INIT_LEVEL_KERNEL);
|
||||
311
kernel/timer.c
311
kernel/timer.c
@@ -1,311 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/mr_initcall.h>
|
||||
#include <kernel/mr_spinlock.h>
|
||||
#include <kernel/mr_timer.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
|
||||
static mr_ktype_t ktype1, ktype2;
|
||||
static mr_kset_t kroot = MR_KSET_INIT(kroot, MR_NULL);
|
||||
static mr_list_t klist = MR_LIST_INIT(klist);
|
||||
static mr_spinlock_t klock = MR_SPINLOCK_INIT();
|
||||
|
||||
MR_INLINE void timer_init(mr_timer_t *timer, mr_ptr_t entry, void *args,
|
||||
mr_tick_t tick) {
|
||||
/* Init timer */
|
||||
mr_list_init(&timer->list);
|
||||
timer->init_tick = tick;
|
||||
timer->timeout_tick = 0;
|
||||
timer->entry = entry;
|
||||
timer->args = args;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t timer_init_add(mr_timer_t *timer, mr_ktype_t *ktype,
|
||||
const char *name, mr_ptr_t entry, void *args,
|
||||
mr_tick_t tick) {
|
||||
/* Init timer */
|
||||
timer_init(timer, entry, args, tick);
|
||||
|
||||
/* Init kobject */
|
||||
mr_kobject_init((mr_kobject_t *)timer, ktype);
|
||||
|
||||
/* Add kobject to kroot */
|
||||
return mr_kobject_add((mr_kobject_t *)timer, (mr_kobject_t *)&kroot, name);
|
||||
}
|
||||
|
||||
mr_err_t mr_timer_init(mr_timer_t *timer, const char *name,
|
||||
void (*entry)(mr_timer_t *, void *), void *args,
|
||||
mr_tick_t tick) {
|
||||
/* Check arguments */
|
||||
if ((!timer) || (MR_KOBJECT_IS_INITED(timer)) || (!name) || (!entry)
|
||||
|| (tick == 0)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Init and add timer */
|
||||
return timer_init_add(timer, &ktype1, name, (mr_ptr_t)entry, args, tick);
|
||||
}
|
||||
|
||||
mr_timer_t *mr_timer_create(const char *name,
|
||||
void (*entry)(mr_timer_t *, void *), void *args,
|
||||
mr_tick_t tick) {
|
||||
mr_timer_t *timer;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!name) || (!entry) || (tick == 0)) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Create timer */
|
||||
timer = mr_malloc(sizeof(mr_timer_t));
|
||||
if (!timer) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Init and add timer */
|
||||
ret = timer_init_add(timer, &ktype2, name, (mr_ptr_t)entry, args, tick);
|
||||
if (ret != 0) {
|
||||
/* Free timer */
|
||||
mr_free(timer);
|
||||
return MR_NULL;
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
MR_INLINE void timer_remove(mr_timer_t *timer) {
|
||||
/* Stop timer if not stopped */
|
||||
if (!mr_list_is_empty(&timer->list)) {
|
||||
mr_list_del(&timer->list);
|
||||
}
|
||||
}
|
||||
|
||||
MR_INLINE void timer_del(mr_timer_t *timer) {
|
||||
int mask;
|
||||
|
||||
/* Lock timer list */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Remove timer from timer list */
|
||||
timer_remove(timer);
|
||||
|
||||
/* Unlock timer list */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_timer_del(mr_timer_t *timer) {
|
||||
/* Get timer */
|
||||
timer = (mr_timer_t *)mr_kobject_get((mr_kobject_t *)timer);
|
||||
if (!timer) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete timer from timer list */
|
||||
timer_del(timer);
|
||||
|
||||
/* Delete kobject */
|
||||
mr_kobject_del((mr_kobject_t *)timer);
|
||||
|
||||
/* Put timer */
|
||||
mr_kobject_put((mr_kobject_t *)timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE void timer_insert(mr_timer_t *timer) {
|
||||
mr_tick_t tick;
|
||||
mr_timer_t *t;
|
||||
mr_list_t *l;
|
||||
|
||||
/* Set timeout tick */
|
||||
tick = timer->init_tick & ~MR_TIMER_PERIODIC;
|
||||
timer->timeout_tick = (mr_tick_t)mr_clock_get() + tick;
|
||||
|
||||
/* Insert timer into timer list */
|
||||
MR_LIST_FOR_EACH(l, &klist) {
|
||||
t = MR_LIST_ENTRY(l, mr_timer_t, list);
|
||||
if ((timer->timeout_tick - t->timeout_tick) < (MR_TICK_MAX / 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Move timer into position */
|
||||
mr_list_move(&timer->list, &t->list);
|
||||
return;
|
||||
}
|
||||
|
||||
/* It is the last timer */
|
||||
mr_list_move(&timer->list, &klist);
|
||||
}
|
||||
|
||||
MR_INLINE void timer_start(mr_timer_t *timer) {
|
||||
int mask;
|
||||
|
||||
/* Lock timer list */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Insert timer into timer list */
|
||||
timer_insert(timer);
|
||||
|
||||
/* Unlock timer list */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_timer_start(mr_timer_t *timer) {
|
||||
/* Get timer */
|
||||
timer = (mr_timer_t *)mr_kobject_get((mr_kobject_t *)timer);
|
||||
if (!timer) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Start timer */
|
||||
timer_start(timer);
|
||||
|
||||
/* Put timer */
|
||||
mr_kobject_put((mr_kobject_t *)timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_timer_stop(mr_timer_t *timer) {
|
||||
/* Get timer */
|
||||
timer = (mr_timer_t *)mr_kobject_get((mr_kobject_t *)timer);
|
||||
if (!timer) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete timer from timer list */
|
||||
timer_del(timer);
|
||||
|
||||
/* Put timer */
|
||||
mr_kobject_put((mr_kobject_t *)timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE void timer_tick_set(mr_timer_t *timer, mr_tick_t tick) {
|
||||
int mask;
|
||||
|
||||
/* Lock timer list */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Set init tick */
|
||||
timer->init_tick = tick;
|
||||
|
||||
/* Unlock timer list */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_timer_tick_set(mr_timer_t *timer, mr_tick_t tick) {
|
||||
/* Check arguments */
|
||||
if (tick == 0) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Get timer */
|
||||
timer = (mr_timer_t *)mr_kobject_get((mr_kobject_t *)timer);
|
||||
if (!timer) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete timer from timer list */
|
||||
timer_del(timer);
|
||||
|
||||
/* Set timer tick */
|
||||
timer_tick_set(timer, tick);
|
||||
|
||||
/* Put timer */
|
||||
mr_kobject_put((mr_kobject_t *)timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE void timer_release1_kobj(mr_kobject_t *kobj) {
|
||||
mr_timer_t *timer;
|
||||
|
||||
/* Get timer */
|
||||
timer = MR_CONTAINER_OF(kobj, mr_timer_t, parent);
|
||||
|
||||
/* Delete timer from timer list */
|
||||
timer_del(timer);
|
||||
}
|
||||
|
||||
MR_INLINE void timer_release2_kobj(mr_kobject_t *kobj) {
|
||||
mr_timer_t *timer;
|
||||
|
||||
/* Get timer */
|
||||
timer = MR_CONTAINER_OF(kobj, mr_timer_t, parent);
|
||||
|
||||
/* Delete timer from timer list */
|
||||
timer_del(timer);
|
||||
|
||||
/* Free timer */
|
||||
mr_free(timer);
|
||||
}
|
||||
|
||||
MR_INLINE void timer_timeout_check(void) {
|
||||
mr_timer_t *timer;
|
||||
mr_tick_t tick;
|
||||
mr_list_t list;
|
||||
int mask;
|
||||
|
||||
/* Lock timer list */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Check timeout timer */
|
||||
while (!mr_list_is_empty(&klist)) {
|
||||
timer = MR_LIST_ENTRY(klist.next, mr_timer_t, list);
|
||||
|
||||
/* Get current tick */
|
||||
tick = (mr_tick_t)mr_clock_get();
|
||||
if ((tick - timer->timeout_tick) >= (MR_TICK_MAX / 2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move timer into operation list */
|
||||
mr_list_init(&list);
|
||||
mr_list_move(&timer->list, &list);
|
||||
|
||||
/* Unlock timer list */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
|
||||
/* Call timer entry */
|
||||
((void (*)(mr_timer_t *, void *))timer->entry)(timer, timer->args);
|
||||
|
||||
/* Lock timer list */
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Timer is no longer yours to operate */
|
||||
if (mr_list_is_empty(&list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tick is periodic */
|
||||
if (timer->init_tick & MR_TIMER_PERIODIC) {
|
||||
timer_insert(timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock timer list */
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
}
|
||||
|
||||
MR_INLINE void mr_timer_kset_init(void) {
|
||||
mr_err_t ret;
|
||||
|
||||
/* Register kset */
|
||||
ret = mr_kset_register(&kroot, "timer");
|
||||
if (ret != 0) {
|
||||
/* It won't hook the clock, so it won't start */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init ktype */
|
||||
mr_ktype_init(&ktype1, timer_release1_kobj);
|
||||
mr_ktype_init(&ktype2, timer_release2_kobj);
|
||||
|
||||
/* Register clock hook */
|
||||
mr_clock_hook_add(-1, timer_timeout_check);
|
||||
}
|
||||
MR_INIT_EXPORT(mr_timer_kset_init, MR_INIT_LEVEL_KERNEL);
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <libc/mr_printfk.h>
|
||||
#if (!defined(MR_USE_LIBC_PRINTFK)) && (!defined(MR_USE_3PARTY_PRINTFK))
|
||||
#include <stdio.h>
|
||||
|
||||
int mr_printfk(const char *fmt, ...) {
|
||||
mr_va_list args;
|
||||
int ret;
|
||||
|
||||
mr_va_start(args, fmt);
|
||||
ret = vprintf(fmt, args);
|
||||
mr_va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mr_snprintfk(char *buf, mr_size_t size, const char *fmt, ...) {
|
||||
mr_va_list args;
|
||||
int ret;
|
||||
|
||||
mr_va_start(args, fmt);
|
||||
ret = vsnprintf(buf, size, fmt, args);
|
||||
mr_va_end(args);
|
||||
return ret;
|
||||
}
|
||||
#endif /* (!defined(MR_USE_LIBC_PRINTFK)) && (!defined(MR_USE_3PARTY_PRINTFK)) */
|
||||
Reference in New Issue
Block a user