diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Kconfig | 9 | ||||
| -rw-r--r-- | src/clock.c | 20 | ||||
| -rw-r--r-- | src/components.c | 30 | ||||
| -rw-r--r-- | src/cpu.c | 2 | ||||
| -rw-r--r-- | src/device.c | 14 | ||||
| -rw-r--r-- | src/idle.c | 186 | ||||
| -rwxr-xr-x | src/ipc.c | 1172 | ||||
| -rw-r--r-- | src/irq.c | 8 | ||||
| -rw-r--r-- | src/kservice.c | 74 | ||||
| -rw-r--r-- | src/mem.c | 48 | ||||
| -rw-r--r-- | src/memheap.c | 102 | ||||
| -rw-r--r-- | src/mempool.c | 7 | ||||
| -rw-r--r-- | src/object.c | 14 | ||||
| -rw-r--r-- | src/scheduler.c | 96 | ||||
| -rw-r--r-- | src/signal.c | 12 | ||||
| -rw-r--r-- | src/slab.c | 24 | ||||
| -rw-r--r-- | src/thread.c | 90 | ||||
| -rw-r--r-- | src/timer.c | 20 |
18 files changed, 1333 insertions, 595 deletions
diff --git a/src/Kconfig b/src/Kconfig index 9a49146dff..a987daab46 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -98,6 +98,11 @@ config IDLE_THREAD_STACK_SIZE int "The stack size of idle thread" default 256 +config SYSTEM_THREAD_STACK_SIZE + int "The stack size of system thread (for defunct etc.)" + depends on RT_USING_SMP + default IDLE_THREAD_STACK_SIZE + config RT_USING_TIMER_SOFT bool "Enable software timer with a timer thread" default y @@ -347,6 +352,10 @@ menu "Kernel Device Object" config RT_CONSOLE_DEVICE_NAME string "the device name for console" default "uart" + + config RT_PRINTF_LONGLONG + bool "rt_kprintf support long long" + default n endif endmenu diff --git a/src/clock.c b/src/clock.c index 0880d8d241..77516b3775 100644 --- a/src/clock.c +++ b/src/clock.c @@ -13,7 +13,8 @@ * 2010-07-13 Bernard fix rt_tick_from_millisecond issue found by kuronca * 2011-06-26 Bernard add rt_tick_set function. * 2018-11-22 Jesven add per cpu tick - * 2020-12-29 Meco Man add function rt_tick_get_millisecond() + * 2020-12-29 Meco Man implement rt_tick_get_millisecond() + * 2021-06-01 Meco Man add critical section projection for rt_tick_increase() */ #include <rthw.h> @@ -22,8 +23,8 @@ #ifdef RT_USING_SMP #define rt_tick rt_cpu_index(0)->tick #else -static rt_tick_t rt_tick = 0; -#endif +static volatile rt_tick_t rt_tick = 0; +#endif /* RT_USING_SMP */ /** * @addtogroup Clock @@ -62,13 +63,16 @@ void rt_tick_set(rt_tick_t tick) void rt_tick_increase(void) { struct rt_thread *thread; + rt_base_t level; + + level = rt_hw_interrupt_disable(); /* increase the global tick */ #ifdef RT_USING_SMP rt_cpu_self()->tick ++; #else ++ rt_tick; -#endif +#endif /* RT_USING_SMP */ /* check time slice */ thread = rt_thread_self(); @@ -78,11 +82,15 @@ void rt_tick_increase(void) { /* change to initialized tick */ thread->remaining_tick = thread->init_tick; - thread->stat |= RT_THREAD_STAT_YIELD; + rt_hw_interrupt_enable(level); rt_schedule(); } + else + { + rt_hw_interrupt_enable(level); + } /* check timer */ rt_timer_check(); @@ -130,7 +138,7 @@ RT_WEAK rt_tick_t rt_tick_get_millisecond(void) #warning "rt-thread cannot provide a correct 1ms-based tick any longer,\ please redefine this function in another file by using a high-precision hard-timer." return 0; -#endif +#endif /* 1000 % RT_TICK_PER_SECOND == 0u */ } /**@}*/ diff --git a/src/components.c b/src/components.c index 9709d0aae2..e156b783e4 100644 --- a/src/components.c +++ b/src/components.c @@ -23,11 +23,11 @@ #ifdef RT_USING_USER_MAIN #ifndef RT_MAIN_THREAD_STACK_SIZE #define RT_MAIN_THREAD_STACK_SIZE 2048 -#endif +#endif /* RT_MAIN_THREAD_STACK_SIZE */ #ifndef RT_MAIN_THREAD_PRIORITY #define RT_MAIN_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 3) -#endif -#endif +#endif /* RT_MAIN_THREAD_PRIORITY */ +#endif /* RT_USING_USER_MAIN */ #ifdef RT_USING_COMPONENTS_INIT /* @@ -98,7 +98,7 @@ void rt_components_board_init(void) { (*fn_ptr)(); } -#endif +#endif /* RT_DEBUG_INIT */ } /** @@ -124,9 +124,9 @@ void rt_components_init(void) { (*fn_ptr)(); } -#endif +#endif /* RT_DEBUG_INIT */ } -#endif /* RT_USING_COMPONENTS_INIT */ +#endif /* RT_USING_COMPONENTS_INIT */ #ifdef RT_USING_USER_MAIN @@ -134,7 +134,7 @@ void rt_application_init(void); void rt_hw_board_init(void); int rtthread_startup(void); -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION extern int $Super$$main(void); /* re-define main function */ int $Sub$$main(void) @@ -167,7 +167,7 @@ int entry(void) ALIGN(8) static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE]; struct rt_thread main_thread; -#endif +#endif /* RT_USING_HEAP */ /* the system main thread */ void main_thread_entry(void *parameter) @@ -177,13 +177,13 @@ void main_thread_entry(void *parameter) #ifdef RT_USING_COMPONENTS_INIT /* RT-Thread components initialization */ rt_components_init(); -#endif +#endif /* RT_USING_COMPONENTS_INIT */ #ifdef RT_USING_SMP rt_hw_secondary_cpu_up(); -#endif +#endif /* RT_USING_SMP */ /* invoke system main function */ -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION { extern int $Super$$main(void); $Super$$main(); /* for ARMCC. */ @@ -211,7 +211,7 @@ void rt_application_init(void) /* if not define RT_USING_HEAP, using to eliminate the warning */ (void)result; -#endif +#endif /* RT_USING_HEAP */ rt_thread_startup(tid); } @@ -237,7 +237,7 @@ int rtthread_startup(void) #ifdef RT_USING_SIGNALS /* signal system initialization */ rt_system_signal_init(); -#endif +#endif /* RT_USING_SIGNALS */ /* create init_thread */ rt_application_init(); @@ -250,7 +250,7 @@ int rtthread_startup(void) #ifdef RT_USING_SMP rt_hw_spin_lock(&_cpus_lock); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* start scheduler */ rt_system_scheduler_start(); @@ -258,4 +258,4 @@ int rtthread_startup(void) /* never reach here */ return 0; } -#endif +#endif /* RT_USING_USER_MAIN */ @@ -185,4 +185,4 @@ void rt_cpus_lock_status_restore(struct rt_thread *thread) } RTM_EXPORT(rt_cpus_lock_status_restore); -#endif +#endif /* RT_USING_SMP */ diff --git a/src/device.c b/src/device.c index 50b83c7692..a9c244d306 100644 --- a/src/device.c +++ b/src/device.c @@ -16,9 +16,9 @@ */ #include <rtthread.h> -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX #include <rtdevice.h> /* for wqueue_init */ -#endif +#endif /* RT_USING_POSIX */ #ifdef RT_USING_DEVICE @@ -36,7 +36,7 @@ #define device_read (dev->read) #define device_write (dev->write) #define device_control (dev->control) -#endif +#endif /* RT_USING_DEVICE_OPS */ /** * This function registers a device driver with specified name. @@ -62,10 +62,10 @@ rt_err_t rt_device_register(rt_device_t dev, dev->ref_count = 0; dev->open_flag = 0; -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX dev->fops = RT_NULL; rt_wqueue_init(&(dev->wait_queue)); -#endif +#endif /* RT_USING_POSIX */ return RT_EOK; } @@ -150,7 +150,7 @@ void rt_device_destroy(rt_device_t dev) rt_free(dev); } RTM_EXPORT(rt_device_destroy); -#endif +#endif /* RT_USING_HEAP */ /** * This function will initialize the specified device @@ -434,4 +434,4 @@ rt_device_set_tx_complete(rt_device_t dev, } RTM_EXPORT(rt_device_set_tx_complete); -#endif +#endif /* RT_USING_DEVICE */ diff --git a/src/idle.c b/src/idle.c index 59868352d8..a571e487cf 100644 --- a/src/idle.c +++ b/src/idle.c @@ -22,38 +22,48 @@ #ifdef RT_USING_MODULE #include <dlmodule.h> -#endif +#endif /* RT_USING_MODULE */ -#if defined (RT_USING_HOOK) +#ifdef RT_USING_HOOK #ifndef RT_USING_IDLE_HOOK #define RT_USING_IDLE_HOOK -#endif -#endif +#endif /* RT_USING_IDLE_HOOK */ +#endif /* RT_USING_HOOK */ #ifndef IDLE_THREAD_STACK_SIZE #if defined (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) #define IDLE_THREAD_STACK_SIZE 256 #else #define IDLE_THREAD_STACK_SIZE 128 -#endif -#endif +#endif /* (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) */ +#endif /* IDLE_THREAD_STACK_SIZE */ #ifdef RT_USING_SMP #define _CPUS_NR RT_CPUS_NR #else #define _CPUS_NR 1 -#endif +#endif /* RT_USING_SMP */ -extern rt_list_t rt_thread_defunct; +static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct);; static struct rt_thread idle[_CPUS_NR]; ALIGN(RT_ALIGN_SIZE) static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE]; +#ifdef RT_USING_SMP +#ifndef SYSTEM_THREAD_STACK_SIZE +#define SYSTEM_THREAD_STACK_SIZE IDLE_THREAD_STACK_SIZE +#endif +static struct rt_thread rt_system_thread; +ALIGN(RT_ALIGN_SIZE) +static rt_uint8_t rt_system_stack[SYSTEM_THREAD_STACK_SIZE]; +static struct rt_semaphore system_sem; +#endif + #ifdef RT_USING_IDLE_HOOK #ifndef RT_IDLE_HOOK_LIST_SIZE #define RT_IDLE_HOOK_LIST_SIZE 4 -#endif +#endif /* RT_IDLE_HOOK_LIST_SIZE */ static void (*idle_hook_list[RT_IDLE_HOOK_LIST_SIZE])(void); @@ -125,45 +135,77 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void)) return ret; } -#endif +#endif /* RT_USING_IDLE_HOOK */ -#ifdef RT_USING_HEAP +#ifdef RT_USING_MODULE /* Return whether there is defunctional thread to be deleted. */ rt_inline int _has_defunct_thread(void) { /* The rt_list_isempty has prototype of "int rt_list_isempty(const rt_list_t *l)". - * So the compiler has a good reason that the rt_thread_defunct list does - * not change within rt_thread_idle_excute thus optimize the "while" loop + * So the compiler has a good reason that the _rt_thread_defunct list does + * not change within rt_thread_defunct_exceute thus optimize the "while" loop * into a "if". * * So add the volatile qualifier here. */ - const volatile rt_list_t *l = (const volatile rt_list_t *)&rt_thread_defunct; + const volatile rt_list_t *l = (const volatile rt_list_t *)&_rt_thread_defunct; return l->next != l; } +#endif /* RT_USING_MODULE */ + +/* enqueue a thread to defunct queue + * it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable + */ +void rt_thread_defunct_enqueue(rt_thread_t thread) +{ + rt_list_insert_after(&_rt_thread_defunct, &thread->tlist); +#ifdef RT_USING_SMP + rt_sem_release(&system_sem); #endif +} + +/* dequeue a thread from defunct queue + * it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable + */ +rt_thread_t rt_thread_defunct_dequeue(void) +{ + rt_thread_t thread = RT_NULL; + rt_list_t *l = &_rt_thread_defunct; + + if (l->next != l) + { + thread = rt_list_entry(l->next, + struct rt_thread, + tlist); + rt_list_remove(&(thread->tlist)); + } + return thread; +} /** * @ingroup Thread * * This function will perform system background job when system idle. */ -void rt_thread_idle_excute(void) +static void rt_defunct_execute(void) { - /* Loop until there is no dead thread. So one call to rt_thread_idle_excute + /* Loop until there is no dead thread. So one call to rt_defunct_execute * will do all the cleanups. */ - /* disable interrupt */ - - RT_DEBUG_NOT_IN_INTERRUPT; - -#ifdef RT_USING_HEAP while (1) { rt_base_t lock; rt_thread_t thread; + void (*cleanup)(struct rt_thread *tid); + +#ifdef RT_USING_MODULE + struct rt_dlmodule *module = RT_NULL; +#endif + RT_DEBUG_NOT_IN_INTERRUPT; + /* disable interrupt */ lock = rt_hw_interrupt_disable(); +#ifdef RT_USING_MODULE /* check whether list is empty */ if (!_has_defunct_thread()) { @@ -171,18 +213,56 @@ void rt_thread_idle_excute(void) break; } /* get defunct thread */ - thread = rt_list_entry(rt_thread_defunct.next, + thread = rt_list_entry(_rt_thread_defunct.next, struct rt_thread, tlist); + module = (struct rt_dlmodule*)thread->module_id; + if (module) + { + dlmodule_destroy(module); + } /* remove defunct thread */ rt_list_remove(&(thread->tlist)); - /* release thread's stack */ - RT_KERNEL_FREE(thread->stack_addr); - /* delete thread object */ - rt_object_delete((rt_object_t)thread); - rt_hw_interrupt_enable(lock); - } +#else + thread = rt_thread_defunct_dequeue(); + if (!thread) + { + rt_hw_interrupt_enable(lock); + break; + } +#endif + /* invoke thread cleanup */ + cleanup = thread->cleanup; + if (cleanup != RT_NULL) + { + rt_hw_interrupt_enable(lock); + cleanup(thread); + lock = rt_hw_interrupt_disable(); + } + +#ifdef RT_USING_SIGNALS + rt_thread_free_sig(thread); +#endif + + /* if it's a system object, not delete it */ + if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) + { + /* detach this object */ + rt_object_detach((rt_object_t)thread); + /* enable interrupt */ + rt_hw_interrupt_enable(lock); + } + else + { + rt_hw_interrupt_enable(lock); +#ifdef RT_USING_HEAP + /* release thread's stack */ + RT_KERNEL_FREE(thread->stack_addr); + /* delete thread object */ + rt_object_delete((rt_object_t)thread); #endif + } + } } extern void rt_system_power_manager(void); @@ -196,28 +276,44 @@ static void rt_thread_idle_entry(void *parameter) rt_hw_secondary_cpu_idle_exec(); } } -#endif +#endif /* RT_USING_SMP */ while (1) { #ifdef RT_USING_IDLE_HOOK rt_size_t i; + void (*idle_hook)(void); for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++) { - if (idle_hook_list[i] != RT_NULL) + idle_hook = idle_hook_list[i]; + if (idle_hook != RT_NULL) { - idle_hook_list[i](); + idle_hook(); } } -#endif +#endif /* RT_USING_IDLE_HOOK */ + +#ifndef RT_USING_SMP + rt_defunct_execute(); +#endif /* RT_USING_SMP */ - rt_thread_idle_excute(); #ifdef RT_USING_PM rt_system_power_manager(); -#endif +#endif /* RT_USING_PM */ + } +} + +#ifdef RT_USING_SMP +static void rt_thread_system_entry(void *parameter) +{ + while (1) + { + rt_sem_take(&system_sem, RT_WAITING_FOREVER); + rt_defunct_execute(); } } +#endif /** * @ingroup SystemInit @@ -244,10 +340,28 @@ void rt_thread_idle_init(void) 32); #ifdef RT_USING_SMP rt_thread_control(&idle[i], RT_THREAD_CTRL_BIND_CPU, (void*)i); -#endif +#endif /* RT_USING_SMP */ /* startup */ rt_thread_startup(&idle[i]); } + +#ifdef RT_USING_SMP + RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2); + + rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO); + + /* create defunct thread */ + rt_thread_init(&rt_system_thread, + "tsystem", + rt_thread_system_entry, + RT_NULL, + rt_system_stack, + sizeof(rt_system_stack), + RT_THREAD_PRIORITY_MAX - 2, + 32); + /* startup */ + rt_thread_startup(&rt_system_thread); +#endif } /** @@ -262,7 +376,7 @@ rt_thread_t rt_thread_idle_gethandler(void) register int id = rt_hw_cpu_id(); #else register int id = 0; -#endif +#endif /* RT_USING_SMP */ return (rt_thread_t)(&idle[id]); } @@ -37,8 +37,8 @@ * 2020-07-29 Meco Man fix thread->event_set/event_info when received an * event without pending * 2020-10-11 Meco Man add value overflow-check code - * 2021-01-03 Meco Man add rt_mb_urgent() - * 2021-01-20 hupu fix priority inversion bug of mutex + * 2021-01-03 Meco Man implement rt_mb_urgent() + * 2021-05-30 Meco Man implement rt_mutex_trytake() */ #include <rtthread.h> @@ -48,7 +48,7 @@ extern void (*rt_object_trytake_hook)(struct rt_object *object); extern void (*rt_object_take_hook)(struct rt_object *object); extern void (*rt_object_put_hook)(struct rt_object *object); -#endif +#endif /* RT_USING_HOOK */ /** * @addtogroup IPC @@ -57,11 +57,16 @@ extern void (*rt_object_put_hook)(struct rt_object *object); /**@{*/ /** - * This function will initialize an IPC object + * @brief This function will initialize an IPC object, such as semaphore, mutex, messagequeue and mailbox. * - * @param ipc the IPC object + * @note Executing this function will complete an initialization of the suspend thread list of the ipc object. * - * @return the operation status, RT_EOK on successful + * @param ipc is a pointer to the IPC object. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * When the return value is any other values, it means the initialization failed. + * + * @warning This function can be called from all IPC initialization and creation. */ rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc) { @@ -71,16 +76,35 @@ rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc) return RT_EOK; } + /** - * This function will suspend a thread to a specified list. IPC object or some - * double-queue object (mailbox etc.) contains this kind of list. + * @brief This function will suspend a thread to a IPC object list. + * + * @param list is a pointer to a suspended thread list of the IPC object. + * + * @param thread is a pointer to the thread object to be suspended. + * + * @param flag is a flag for the thread object to be suspended. It determines how the thread is suspended. + * The flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to use + * RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this semaphore will become non-real-time threads. * - * @param list the IPC suspended thread list - * @param thread the thread object to be suspended - * @param flag the IPC object flag, - * which shall be RT_IPC_FLAG_FIFO/RT_IPC_FLAG_PRIO. + * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed. + * When the return value is any other values, it means the initialization failed. * - * @return the operation status, RT_EOK on successful + * @warning This function can ONLY be called in the thread context, you can use RT_DEBUG_IN_THREAD_CONTEXT to + * check the context. + * In addition, this function is generally called by the following functions: + * rt_sem_take(), rt_mutex_take(), rt_event_recv(), rt_mb_send_wait(), + * rt_mb_recv(), rt_mq_recv(), rt_mq_send_wait() */ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, struct rt_thread *thread, @@ -93,7 +117,7 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, { case RT_IPC_FLAG_FIFO: rt_list_insert_before(list, &(thread->tlist)); - break; + break; /* RT_IPC_FLAG_FIFO */ case RT_IPC_FLAG_PRIO: { @@ -121,7 +145,7 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, if (n == list) rt_list_insert_before(list, &(thread->tlist)); } - break; + break;/* RT_IPC_FLAG_PRIO */ default: RT_ASSERT(0); @@ -131,14 +155,25 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, return RT_EOK; } + /** - * This function will resume the first thread in the list of a IPC object: - * - remove the thread from suspend queue of IPC object - * - put the thread into system ready queue + * @brief This function will resume a thread. + * + * @note This function will resume the first thread in the list of a IPC object. + * 1. remove the thread from suspend queue of a IPC object. + * 2. put the thread into system ready queue. + * + * By contrast, the rt_ipc_list_resume_all() function will resume all suspended threads + * in the list of a IPC object. * - * @param list the thread list + * @param list is a pointer to a suspended thread list of the IPC object. * - * @return the operation status, RT_EOK on successful + * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed. + * When the return value is any other values, it means this operation failed. + * + * @warning This function is generally called by the following functions: + * rt_sem_release(), rt_mutex_release(), rt_mb_send_wait(), rt_mq_send_wait(), + * rt_mb_urgent(), rt_mb_recv(), rt_mq_urgent(), rt_mq_recv(), */ rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list) { @@ -155,13 +190,19 @@ rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list) return RT_EOK; } + /** - * This function will resume all suspended threads in a list, including - * suspend list of IPC object and private list of mailbox etc. + * @brief This function will resume all suspended threads in the IPC object list, + * including the suspended list of IPC object, and private list of mailbox etc. + * + * @note This function will resume all threads in the IPC object list. + * By contrast, the rt_ipc_list_resume() function will resume a suspended thread in the list of a IPC object. + * + * @param list is a pointer to a suspended thread list of the IPC object. * - * @param list of the threads to resume + * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed. + * When the return value is any other values, it means this operation failed. * - * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list) { @@ -193,42 +234,51 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list) return RT_EOK; } +/**@}*/ + +#ifdef RT_USING_SEMAPHORE /** - * This function will get the highest priority from the specified - * list of threads - * - * @param list of the threads - * - * @return the highest priority + * @addtogroup semaphore */ -rt_uint8_t rt_ipc_get_highest_priority(rt_list_t *list) -{ - struct rt_list_node *n; - struct rt_thread *sthread; - rt_uint8_t priority = RT_THREAD_PRIORITY_MAX - 1; - - for (n = list->next; n != list; n = n->next) - { - sthread = rt_list_entry(n, struct rt_thread, tlist); - priority = priority < sthread->current_priority ? - priority : - sthread->current_priority; - } - return priority; -} - -#ifdef RT_USING_SEMAPHORE +/**@{*/ /** - * This function will initialize a semaphore and put it under control of - * resource management. + * @brief This function will initialize a static semaphore object. + * + * @note For the static semaphore object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_sem_create() function will allocate memory space automatically and initialize + * the semaphore. + * + * @see rt_sem_create() + * + * @param sem is a pointer to the semaphore to initialize. It is assumed that storage for the semaphore will be + * allocated in your application. + * + * @param name is a pointer to the name you would like to give the semaphore. * - * @param sem the semaphore object - * @param name the name of semaphore - * @param value the initial value of semaphore - * @param flag the flag of semaphore + * @param value is the initial value for the semaphore. + * If used to share resources, you should initialize the value as the number of available resources. + * If used to signal the occurrence of an event, you should initialize the value as 0. * - * @return the operation status, RT_EOK on successful + * @param flag is the semaphore flag, which determines the queuing way of how multiple threads wait + * when the semaphore is not available. + * The semaphore flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this semaphore will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_sem_init(rt_sem_t sem, const char *name, @@ -254,14 +304,24 @@ rt_err_t rt_sem_init(rt_sem_t sem, } RTM_EXPORT(rt_sem_init); + /** - * This function will detach a semaphore from resource management + * @brief This function will detach a static semaphore object. + * + * @note This function is used to detach a static semaphore object which is initialized by rt_sem_init() function. + * By contrast, the rt_sem_delete() function will delete a semaphore object. + * When the semaphore is successfully detached, it will resume all suspended threads in the semaphore list. * - * @param sem the semaphore object + * @see rt_sem_delete() * - * @return the operation status, RT_EOK on successful + * @param sem is a pointer to a semaphore object to be detached. * - * @see rt_sem_delete + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the semaphore detach failed. + * + * @warning This function can ONLY detach a static semaphore initialized by the rt_sem_init() function. + * If the semaphore is created by the rt_sem_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_sem_delete() function to complete the deletion. */ rt_err_t rt_sem_detach(rt_sem_t sem) { @@ -282,15 +342,36 @@ RTM_EXPORT(rt_sem_detach); #ifdef RT_USING_HEAP /** - * This function will create a semaphore from system resource + * @brief Creating a semaphore object. + * + * @note For the semaphore object, its memory space is allocated automatically. + * By contrast, the rt_sem_init() function will initialize a static semaphore object. * - * @param name the name of semaphore - * @param value the initial value of semaphore - * @param flag the flag of semaphore + * @see rt_sem_init() * - * @return the created semaphore, RT_NULL on error happen + * @param name is a pointer to the name you would like to give the semaphore. * - * @see rt_sem_init + * @param value is the initial value for the semaphore. + * If used to share resources, you should initialize the value as the number of available resources. + * If used to signal the occurrence of an event, you should initialize the value as 0. + * + * @param flag is the semaphore flag, which determines the queuing way of how multiple threads wait + * when the semaphore is not available. + * The semaphore flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this semaphore will become non-real-time threads. + * + * @return Return a pointer to the semaphore object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can NOT be called in interrupt context. You can use macor RT_DEBUG_NOT_IN_INTERRUPT to check it. */ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) { @@ -317,14 +398,24 @@ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) } RTM_EXPORT(rt_sem_create); + /** - * This function will delete a semaphore object and release the memory + * @brief This function will delete a semaphore object and release the memory space. + * + * @note This function is used to delete a semaphore object which is created by the rt_sem_create() function. + * By contrast, the rt_sem_detach() function will detach a static semaphore object. + * When the semaphore is successfully deleted, it will resume all suspended threads in the semaphore list. + * + * @see rt_sem_detach() * - * @param sem the semaphore object + * @param sem is a pointer to a semaphore object to be deleted. * - * @return the error code + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore detach failed. * - * @see rt_sem_detach + * @warning This function can ONLY delete a semaphore initialized by the rt_sem_create() function. + * If the semaphore is initialized by the rt_sem_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_sem_detach() function to complete the detachment. */ rt_err_t rt_sem_delete(rt_sem_t sem) { @@ -344,16 +435,31 @@ rt_err_t rt_sem_delete(rt_sem_t sem) return RT_EOK; } RTM_EXPORT(rt_sem_delete); -#endif +#endif /* RT_USING_HEAP */ + /** - * This function will take a semaphore, if the semaphore is unavailable, the - * thread shall wait for a specified time. + * @brief This function will take a semaphore, if the semaphore is unavailable, the thread shall wait for + * the semaphore up to a specified time. + * + * @note When this function is called, the count value of the sem->value will decrease 1 until it is equal to 0. + * When the sem->value is 0, it means that the semaphore is unavailable. At this time, it will suspend the + * thread preparing to take the semaphore. + * On the contrary, the rt_sem_release() function will increase the count value of sem->value by 1 each time. + * + * @see rt_sem_trytake() + * + * @param sem is a pointer to a semaphore object. + * + * @param time is a timeout period (unit: an OS tick). If the semaphore is unavailable, the thread will wait for + * the semaphore up to the amount of time specified by the argument. + * NOTE: Generally, we use the macro RT_WAITING_FOREVER to set this parameter, which means that when the + * semaphore is unavailable, the thread will be waitting forever. * - * @param sem the semaphore object - * @param time the waiting time + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore take failed. * - * @return the error code + * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context. */ rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time) { @@ -443,26 +549,39 @@ rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time) } RTM_EXPORT(rt_sem_take); + /** - * This function will try to take a semaphore and immediately return + * @brief This function will try to take a semaphore, if the semaphore is unavailable, the thread returns immediately. + * + * @note This function is very similar to the rt_sem_take() function, when the semaphore is not available, + * the rt_sem_trytake() function will return immediately without waiting for a timeout. + * In other words, rt_sem_trytake(sem) has the same effect as rt_sem_take(sem, 0). * - * @param sem the semaphore object + * @see rt_sem_take() * - * @return the error code + * @param sem is a pointer to a semaphore object. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore take failed. */ rt_err_t rt_sem_trytake(rt_sem_t sem) { - return rt_sem_take(sem, 0); + return rt_sem_take(sem, RT_WAITING_NO); } RTM_EXPORT(rt_sem_trytake); + /** - * This function will release a semaphore, if there are threads suspended on - * semaphore, it will be waked up. + * @brief This function will release a semaphore. If there is thread suspended on the semaphore, it will get resumed. * - * @param sem the semaphore object + * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object + * will be resumed, and a thread scheduling (rt_schedule) will be executed. + * If no threads are suspended on this semaphore, the count value sem->value of this semaphore will increase by 1. * - * @return the error code + * @param sem is a pointer to a semaphore object. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore release failed. */ rt_err_t rt_sem_release(rt_sem_t sem) { @@ -515,14 +634,20 @@ rt_err_t rt_sem_release(rt_sem_t sem) } RTM_EXPORT(rt_sem_release); + /** - * This function can get or set some extra attributions of a semaphore object. + * @brief This function will set some extra attributions of a semaphore object. + * + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the semaphore. + * + * @param sem is a pointer to a semaphore object. * - * @param sem the semaphore object - * @param cmd the execution command - * @param arg the execution argument + * @param cmd is a command word used to configure some attributions of the semaphore. * - * @return the error code + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) { @@ -558,21 +683,46 @@ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_sem_control); -#endif /* end of RT_USING_SEMAPHORE */ + +/**@}*/ +#endif /* RT_USING_SEMAPHORE */ #ifdef RT_USING_MUTEX /** - * This function will initialize a mutex and put it under control of resource - * management. + * @addtogroup mutex + */ + +/**@{*/ + +/** + * @brief Initialize a static mutex object. + * + * @note For the static mutex object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_mutex_create() function will automatically allocate memory space + * and initialize the mutex. + * + * @see rt_mutex_create() + * + * @param mutex is a pointer to the mutex to initialize. It is assumed that storage for the mutex will be + * allocated in your application. + * + * @param name is a pointer to the name that given to the mutex. + * + * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait + * when the mutex is not available. + * NOTE: The mutex flag can ONLY be RT_IPC_FLAG_PRIO. Using RT_IPC_FLAG_FIFO will seriously affect + * the real-time performance of the system. * - * @param mutex the mutex object - * @param name the name of mutex - * @param flag the flag of mutex + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. * - * @return the operation status, RT_EOK on successful + * @warning This function can ONLY be called from threads. */ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) { + (void)flag; + /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -587,21 +737,31 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) mutex->original_priority = 0xFF; mutex->hold = 0; - /* set flag */ - mutex->parent.parent.flag = flag; + /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ + mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return RT_EOK; } RTM_EXPORT(rt_mutex_init); + /** - * This function will detach a mutex from resource management + * @brief This function will detach a static mutex object. + * + * @note This function is used to detach a static mutex object which is initialized by rt_mutex_init() function. + * By contrast, the rt_mutex_delete() function will delete a mutex object. + * When the mutex is successfully detached, it will resume all suspended threads in the mutex list. * - * @param mutex the mutex object + * @see rt_mutex_delete() * - * @return the operation status, RT_EOK on successful + * @param mutex is a pointer to a mutex object to be detached. * - * @see rt_mutex_delete + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the mutex detach failed. + * + * @warning This function can ONLY detach a static mutex initialized by the rt_mutex_init() function. + * If the mutex is created by the rt_mutex_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_mutex_delete() function to complete the deletion. */ rt_err_t rt_mutex_detach(rt_mutex_t mutex) { @@ -613,7 +773,7 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex) /* wakeup all suspended threads */ rt_ipc_list_resume_all(&(mutex->parent.suspend_thread)); - /* detach semaphore object */ + /* detach mutex object */ rt_object_detach(&(mutex->parent.parent)); return RT_EOK; @@ -622,18 +782,28 @@ RTM_EXPORT(rt_mutex_detach); #ifdef RT_USING_HEAP /** - * This function will create a mutex from system resource + * @brief This function will create a mutex object. * - * @param name the name of mutex - * @param flag the flag of mutex + * @note For the mutex object, its memory space is automatically allocated. + * By contrast, the rt_mutex_init() function will initialize a static mutex object. * - * @return the created mutex, RT_NULL on error happen + * @see rt_mutex_init() * - * @see rt_mutex_init + * @param name is a pointer to the name that given to the mutex. + * + * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait + * when the mutex is not available. + * NOTE: The mutex flag can ONLY be RT_IPC_FLAG_PRIO. Using RT_IPC_FLAG_FIFO will seriously affect + * the real-time performance of the system. + * + * @return Return a pointer to the mutex object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can ONLY be called from threads. */ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) { struct rt_mutex *mutex; + (void)flag; RT_DEBUG_NOT_IN_INTERRUPT; @@ -650,21 +820,31 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) mutex->original_priority = 0xFF; mutex->hold = 0; - /* set flag */ - mutex->parent.parent.flag = flag; + /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ + mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return mutex; } RTM_EXPORT(rt_mutex_create); + /** - * This function will delete a mutex object and release the memory + * @brief This function will delete a mutex object and release this memory space. * - * @param mutex the mutex object + * @note This function is used to delete a mutex object which is created by the rt_mutex_create() function. + * By contrast, the rt_mutex_detach() function will detach a static mutex object. + * When the mutex is successfully deleted, it will resume all suspended threads in the mutex list. * - * @return the error code + * @see rt_mutex_detach() * - * @see rt_mutex_detach + * @param mutex is a pointer to a mutex object to be deleted. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex detach failed. + * + * @warning This function can ONLY delete a mutex initialized by the rt_mutex_create() function. + * If the mutex is initialized by the rt_mutex_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_mutex_detach() function to complete the detachment. */ rt_err_t rt_mutex_delete(rt_mutex_t mutex) { @@ -684,16 +864,31 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex) return RT_EOK; } RTM_EXPORT(rt_mutex_delete); -#endif +#endif /* RT_USING_HEAP */ + /** - * This function will take a mutex, if the mutex is unavailable, the - * thread shall wait for a specified time. + * @brief This function will take a mutex, if the mutex is unavailable, the thread shall wait for + * the mutex up to a specified time. + * + * @note When this function is called, the count value of the sem->value will decrease 1 until it is equal to 0. + * When the sem->value is 0, it means that the mutex is unavailable. At this time, it will suspend the + * thread preparing to take the mutex. + * On the contrary, the rt_sem_release() function will increase the count value of sem->value by 1 each time. + * + * @see rt_mutex_trytake() * - * @param mutex the mutex object - * @param time the waiting time + * @param mutex is a pointer to a mutex object. * - * @return the error code + * @param time is a timeout period (unit: an OS tick). If the mutex is unavailable, the thread will wait for + * the mutex up to the amount of time specified by the argument. + * NOTE: Generally, we set this parameter to RT_WAITING_FOREVER, which means that when the mutex is unavailable, + * the thread will be waitting forever. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex take failed. + * + * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context. */ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time) { @@ -739,7 +934,7 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time) { #ifdef RT_USING_SIGNALS __again: -#endif /* end of RT_USING_SIGNALS */ +#endif /* RT_USING_SIGNALS */ /* The value of mutex is 1 in initial status. Therefore, if the * value is great than 0, it indicates the mutex is avaible. */ @@ -819,7 +1014,7 @@ __again: #ifdef RT_USING_SIGNALS /* interrupt by signal, try it again */ if (thread->error == -RT_EINTR) goto __again; -#endif /* end of RT_USING_SIGNALS */ +#endif /* RT_USING_SIGNALS */ /* return error */ return thread->error; @@ -843,20 +1038,46 @@ __again: } RTM_EXPORT(rt_mutex_take); + /** - * This function will release a mutex, if there are threads suspended on mutex, - * it will be waked up. + * @brief This function will try to take a mutex, if the mutex is unavailable, the thread returns immediately. + * + * @note This function is very similar to the rt_mutex_take() function, when the mutex is not available, + * except that rt_mutex_trytake() will return immediately without waiting for a timeout + * when the mutex is not available. + * In other words, rt_mutex_trytake(mutex) has the same effect as rt_mutex_take(mutex, 0). * - * @param mutex the mutex object + * @see rt_mutex_take() * - * @return the error code + * @param mutex is a pointer to a mutex object. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex take failed. + */ +rt_err_t rt_mutex_trytake(rt_mutex_t mutex) +{ + return rt_mutex_take(mutex, RT_WAITING_NO); +} +RTM_EXPORT(rt_mutex_trytake); + + +/** + * @brief This function will release a mutex. If there is thread suspended on the mutex, the thread will be resumed. + * + * @note If there are threads suspended on this mutex, the first thread in the list of this mutex object + * will be resumed, and a thread scheduling (rt_schedule) will be executed. + * If no threads are suspended on this mutex, the count value mutex->value of this mutex will increase by 1. + * + * @param mutex is a pointer to a mutex object. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex release failed. */ rt_err_t rt_mutex_release(rt_mutex_t mutex) { register rt_base_t temp; struct rt_thread *thread; rt_bool_t need_schedule; - rt_uint8_t max_priority_in_queue = RT_THREAD_PRIORITY_MAX - 1; /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -918,21 +1139,6 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) mutex->owner = thread; mutex->original_priority = thread->current_priority; - /* Priority adjustment occurs only when the following conditions - * are met simultaneously: - * 1.The type of mutex is RT_IPC_FLAG_FIFO; - * 2.The priority of the thread to be resumed is not equal to the - * highest priority in the queue; - */ - max_priority_in_queue = rt_ipc_get_highest_priority(&mutex->parent.suspend_thread); - if (mutex->parent.parent.flag == RT_IPC_FLAG_FIFO && - thread->current_priority != max_priority_in_queue) - { - rt_thread_control(thread, - RT_THREAD_CTRL_CHANGE_PRIORITY, - &(max_priority_in_queue)); - } - if(mutex->hold < RT_MUTEX_HOLD_MAX) { mutex->hold ++; @@ -978,14 +1184,20 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) } RTM_EXPORT(rt_mutex_release); + /** - * This function can get or set some extra attributions of a mutex object. + * @brief This function will set some extra attributions of a mutex object. + * + * @note Currently this function does not implement the control function. + * + * @param mutex is a pointer to a mutex object. + * + * @param cmd is a command word used to configure some attributions of the mutex. * - * @param mutex the mutex object - * @param cmd the execution command - * @param arg the execution argument + * @param arg is the argument of the function to execute the command. * - * @return the error code + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg) { @@ -996,18 +1208,54 @@ rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mutex_control); -#endif /* end of RT_USING_MUTEX */ + +/**@}*/ +#endif /* RT_USING_MUTEX */ #ifdef RT_USING_EVENT /** - * This function will initialize an event and put it under control of resource - * management. + * @addtogroup event + */ + +/**@{*/ + +/** + * @brief The function will initialize a static event object. + * + * @note For the static event object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_event_create() function will allocate memory space automatically + * and initialize the event. + * + * @see rt_event_create() * - * @param event the event object - * @param name the name of event - * @param flag the flag of event + * @param event is a pointer to the event to initialize. It is assumed that storage for the event + * will be allocated in your application. * - * @return the operation status, RT_EOK on successful + * @param name is a pointer to the name that given to the event. + * + * @param value is the initial value for the event. + * If want to share resources, you should initialize the value as the number of available resources. + * If want to signal the occurrence of an event, you should initialize the value as 0. + * + * @param flag is the event flag, which determines the queuing way of how multiple threads wait + * when the event is not available. + * The event flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this event will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag) { @@ -1030,12 +1278,24 @@ rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag) } RTM_EXPORT(rt_event_init); + /** - * This function will detach an event object from resource management + * @brief This function will detach a static event object. + * + * @note This function is used to detach a static event object which is initialized by rt_event_init() function. + * By contrast, the rt_event_delete() function will delete an event object. + * When the event is successfully detached, it will resume all suspended threads in the event list. * - * @param event the event object + * @see rt_event_delete() * - * @return the operation status, RT_EOK on successful + * @param event is a pointer to an event object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the event detach failed. + * + * @warning This function can ONLY detach a static event initialized by the rt_event_init() function. + * If the event is created by the rt_event_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_event_delete() function to complete the deletion. */ rt_err_t rt_event_detach(rt_event_t event) { @@ -1056,12 +1316,32 @@ RTM_EXPORT(rt_event_detach); #ifdef RT_USING_HEAP /** - * This function will create an event object from system resource + * @brief Creating an event object. + * + * @note For the event object, its memory space is allocated automatically. + * By contrast, the rt_event_init() function will initialize a static event object. + * + * @see rt_event_init() + * + * @param name is a pointer to the name that given to the event. + * + * @param flag is the event flag, which determines the queuing way of how multiple threads wait when the event + * is not available. + * The event flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). * - * @param name the name of event - * @param flag the flag of event + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this event will become non-real-time threads. * - * @return the created event, RT_NULL on error happen + * @return Return a pointer to the event object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can ONLY be called from threads. */ rt_event_t rt_event_create(const char *name, rt_uint8_t flag) { @@ -1087,12 +1367,24 @@ rt_event_t rt_event_create(const char *name, rt_uint8_t flag) } RTM_EXPORT(rt_event_create); + /** - * This function will delete an event object and release the memory + * @brief This function will delete an event object and release the memory space. + * + * @note This function is used to delete an event object which is created by the rt_event_create() function. + * By contrast, the rt_event_detach() function will detach a static event object. + * When the event is successfully deleted, it will resume all suspended threads in the event list. + * + * @see rt_event_detach() + * + * @param event is a pointer to an event object to be deleted. * - * @param event the event object + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the event detach failed. * - * @return the error code + * @warning This function can ONLY delete an event initialized by the rt_event_create() function. + * If the event is initialized by the rt_event_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_event_detach() function to complete the detachment. */ rt_err_t rt_event_delete(rt_event_t event) { @@ -1112,16 +1404,25 @@ rt_err_t rt_event_delete(rt_event_t event) return RT_EOK; } RTM_EXPORT(rt_event_delete); -#endif +#endif /* RT_USING_HEAP */ + /** - * This function will send an event to the event object, if there are threads - * suspended on event object, it will be waked up. + * @brief This function will send an event to the event object. + * If there is a thread suspended on the event, the thread will be resumed. + * + * @note When using this function, you need to use the parameter (set) to specify the event flag of the event object, + * then the function will traverse the list of suspended threads waiting on the event object. + * If there is a thread suspended on the event, and the thread's event_info and the event flag of + * the current event object matches, the thread will be resumed. * - * @param event the event object - * @param set the event set + * @param event is a pointer to the event object to be sent. * - * @return the error code + * @param set is a flag that you will set for this event's flag. + * You can set an event flag, or you can set multiple flags through OR logic operation. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the event detach failed. */ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) { @@ -1215,18 +1516,38 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) } RTM_EXPORT(rt_event_send); + /** - * This function will receive an event from event object, if the event is - * unavailable, the thread shall wait for a specified time. + * @brief This function will receive an event from event object. if the event is unavailable, the thread shall wait for + * the event up to a specified time. + * + * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object + * will be resumed, and a thread scheduling (rt_schedule) will be executed. + * If no threads are suspended on this semaphore, the count value sem->value of this semaphore will increase by 1. + * + * @param event is a pointer to the event object to be received. + * + * @param set is a flag that you will set for this event's flag. + * You can set an event flag, or you can set multiple flags through OR logic operation. + * + * @param option is the option of this receiving event, it indicates how the receiving event is operated. + * The option can be one or more of the following values, When selecting multiple values,use logical OR to operate. + * (NOTE: RT_EVENT_FLAG_OR and RT_EVENT_FLAG_AND can only select one): + * + * + * RT_EVENT_FLAG_OR The thread select to use logical OR to receive the event. + * + * RT_EVENT_FLAG_AND The thread select to use logical OR to receive the event. + * + * RT_EVENT_FLAG_CLEAR When the thread receives the corresponding event, the function + * determines whether to clear the event flag. + * + * @param timeout is a timeout period (unit: an OS tick). * - * @param event the fast event object - * @param set the interested event set - * @param option the receive option, either RT_EVENT_FLAG_AND or - * RT_EVENT_FLAG_OR should be set. - * @param timeout the waiting time - * @param recved the received event, if you don't care, RT_NULL can be set. + * @param recved is a pointer to the received event. If you don't care about this value, you can use RT_NULL to set. * - * @return the error code + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore release failed. */ rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, @@ -1350,14 +1671,20 @@ rt_err_t rt_event_recv(rt_event_t event, } RTM_EXPORT(rt_event_recv); + /** - * This function can get or set some extra attributions of an event object. + * @brief This function will set some extra attributions of an event object. + * + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the event. + * + * @param event is a pointer to an event object. * - * @param event the event object - * @param cmd the execution command - * @param arg the execution argument + * @param cmd is a command word used to configure some attributions of the event. * - * @return the error code + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) { @@ -1389,20 +1716,55 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_event_control); -#endif /* end of RT_USING_EVENT */ + +/**@}*/ +#endif /* RT_USING_EVENT */ #ifdef RT_USING_MAILBOX /** - * This function will initialize a mailbox and put it under control of resource - * management. + * @addtogroup mailbox + */ + +/**@{*/ + +/** + * @brief Initialize a static mailbox object. + * + * @note For the static mailbox object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_mb_create() function will allocate memory space automatically and initialize the mailbox. + * + * @see rt_mb_create() + * + * @param mb is a pointer to the mailbox to initialize. + * It is assumed that storage for the mailbox will be allocated in your application. + * + * @param name is a pointer to the name that given to the mailbox. + * + * @param msgpoll is a pointer to the starting address of the memory space you allocated for the mailbox in advance. + * In other words, msgpoll is a pointer to the mailbox buffer of the starting address. + * + * @param size is the maximum number of mails in the mailbox. + * For example, when the mailbox buffer capacity is N, size is N/4. + * + * @param flag is the mailbox flag, which determines the queuing way of how multiple threads wait + * when the mailbox is not available. + * The mailbox flag can be ONE of the following values: * - * @param mb the mailbox object - * @param name the name of mailbox - * @param msgpool the begin address of buffer to save received mail - * @param size the size of mailbox - * @param flag the flag of mailbox + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. * - * @return the operation status, RT_EOK on successful + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this mailbox will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_mb_init(rt_mailbox_t mb, const char *name, @@ -1435,12 +1797,24 @@ rt_err_t rt_mb_init(rt_mailbox_t mb, } RTM_EXPORT(rt_mb_init); + /** - * This function will detach a mailbox from resource management + * @brief This function will detach a static mailbox object. + * + * @note This function is used to detach a static mailbox object which is initialized by rt_mb_init() function. + * By contrast, the rt_mb_delete() function will delete a mailbox object. + * When the mailbox is successfully detached, it will resume all suspended threads in the mailbox list. * - * @param mb the mailbox object + * @see rt_mb_delete() * - * @return the operation status, RT_EOK on successful + * @param mb is a pointer to a mailbox object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the mailbox detach failed. + * + * @warning This function can ONLY detach a static mailbox initialized by the rt_mb_init() function. + * If the mailbox is created by the rt_mb_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_mb_delete() function to complete the deletion. */ rt_err_t rt_mb_detach(rt_mailbox_t mb) { @@ -1463,13 +1837,35 @@ RTM_EXPORT(rt_mb_detach); #ifdef RT_USING_HEAP /** - * This function will create a mailbox object from system resource + * @brief Creating a mailbox object. + * + * @note For the mailbox object, its memory space is allocated automatically. + * By contrast, the rt_mb_init() function will initialize a static mailbox object. + * + * @see rt_mb_init() * - * @param name the name of mailbox - * @param size the size of mailbox - * @param flag the flag of mailbox + * @param name is a pointer that given to the mailbox. * - * @return the created mailbox, RT_NULL on error happen + * @param size is the maximum number of mails in the mailbox. + * For example, when mailbox buffer capacity is N, size is N/4. + * + * @param flag is the mailbox flag, which determines the queuing way of how multiple threads wait + * when the mailbox is not available. + * The mailbox flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this mailbox will become non-real-time threads. + * + * @return Return a pointer to the mailbox object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can ONLY be called from threads. */ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) { @@ -1509,12 +1905,24 @@ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) } RTM_EXPORT(rt_mb_create); + /** - * This function will delete a mailbox object and release the memory + * @brief This function will delete a mailbox object and release the memory space. + * + * @note This function is used to delete a mailbox object which is created by the rt_mb_create() function. + * By contrast, the rt_mb_detach() function will detach a static mailbox object. + * When the mailbox is successfully deleted, it will resume all suspended threads in the mailbox list. + * + * @see rt_mb_detach() * - * @param mb the mailbox object + * @param mb is a pointer to a mailbox object to be deleted. * - * @return the error code + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. + * + * @warning This function can only delete mailbox created by the rt_mb_create() function. + * If the mailbox is initialized by the rt_mb_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_mb_detach() function to complete the detachment. */ rt_err_t rt_mb_delete(rt_mailbox_t mb) { @@ -1540,17 +1948,31 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb) return RT_EOK; } RTM_EXPORT(rt_mb_delete); -#endif +#endif /* RT_USING_HEAP */ + /** - * This function will send a mail to mailbox object. If the mailbox is full, - * current thread will be suspended until timeout. + * @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox, + * the thread will be resumed. + * + * @note When using this function to send a mail, if the mailbox if fully used, the current thread will + * wait for a timeout. If the set timeout time is reached and there is still no space available, + * the sending thread will be resumed and an error code will be returned. + * By contrast, the rt_mb_send() function will return an error code immediately without waiting time + * when the mailbox if fully used. + * + * @see rt_mb_send() + * + * @param mb is a pointer to the mailbox object to be sent. * - * @param mb the mailbox object - * @param value the mail - * @param timeout the waiting time + * @param value is a value to the content of the mail you want to send. * - * @return the error code + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. + * + * @warning This function can be called in interrupt context and thread context. */ rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_ubase_t value, @@ -1682,15 +2104,23 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb, } RTM_EXPORT(rt_mb_send_wait); + /** - * This function will send a mail to mailbox object, if there are threads - * suspended on mailbox object, it will be waked up. This function will return - * immediately, if you want blocking send, use rt_mb_send_wait instead. + * @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox, + * the thread will be resumed. + * + * @note When using this function to send a mail, if the mailbox is fully used, this function will return an error + * code immediately without waiting time. + * By contrast, the rt_mb_send_wait() function is set a timeout to wait for the mail to be sent. * - * @param mb the mailbox object - * @param value the mail + * @see rt_mb_send_wait() * - * @return the error code + * @param mb is a pointer to the mailbox object to be sent. + * + * @param value is a value to the content of the mail you want to send. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. */ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) { @@ -1698,15 +2128,22 @@ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) } RTM_EXPORT(rt_mb_send); + /** - * This function will send an urgent mail to mailbox object, if there are threads - * suspended on mailbox object, it will be waked up. This function will return - * immediately. + * @brief This function will send an urgent mail to the mailbox object. + * + * @note This function is almost the same as the rt_mb_send() function. The only difference is that + * when sending an urgent mail, the mail will be placed at the head of the mail queue so that + * the recipient can receive the urgent mail first. * - * @param mb the mailbox object - * @param value the mail + * @see rt_mb_send() * - * @return the error code + * @param mb is a pointer to the mailbox object to be sent. + * + * @param value is the content of the mail you want to send. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. */ rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) { @@ -1763,15 +2200,24 @@ rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) } RTM_EXPORT(rt_mb_urgent); + /** - * This function will receive a mail from mailbox object, if there is no mail - * in mailbox object, the thread shall wait for a specified time. + * @brief This function will receive a mail from mailbox object, if there is no mail in mailbox object, + * the thread shall wait for a specified time. + * + * @note Only when there is mail in the mailbox, the receiving thread can get the mail immediately and + * return RT_EOK, otherwise the receiving thread will be suspended until the set timeout. If the mail + * is still not received within the specified time, it will return-RT_ETIMEOUT. * - * @param mb the mailbox object - * @param value the received mail will be saved in - * @param timeout the waiting time + * @param mb is a pointer to the mailbox object to be received. * - * @return the error code + * @param value is a flag that you will set for this mailbox's flag. + * You can set an mailbox flag, or you can set multiple flags through OR logic operations. + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox release failed. */ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout) { @@ -1904,14 +2350,20 @@ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout) } RTM_EXPORT(rt_mb_recv); + /** - * This function can get or set some extra attributions of a mailbox object. + * @brief This function will set some extra attributions of a mailbox object. + * + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the mailbox. + * + * @param mb is a pointer to a mailbox object. * - * @param mb the mailbox object - * @param cmd the execution command - * @param arg the execution argument + * @param cmd is a command used to configure some attributions of the mailbox. * - * @return the error code + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) { @@ -1947,26 +2399,64 @@ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mb_control); -#endif /* end of RT_USING_MAILBOX */ + +/**@}*/ +#endif /* RT_USING_MAILBOX */ #ifdef RT_USING_MESSAGEQUEUE +/** + * @addtogroup messagequeue + */ + +/**@{*/ + struct rt_mq_message { struct rt_mq_message *next; }; + /** - * This function will initialize a message queue and put it under control of - * resource management. + * @brief Initialize a static messagequeue object. + * + * @note For the static messagequeue object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_mq_create() function will allocate memory space automatically + * and initialize the messagequeue. + * + * @see rt_mq_create() + * + * @param mq is a pointer to the messagequeue to initialize. It is assumed that storage for + * the messagequeue will be allocated in your application. + * + * @param name is a pointer to the name that given to the messagequeue. * - * @param mq the message object - * @param name the name of message queue - * @param msgpool the beginning address of buffer to save messages - * @param msg_size the maximum size of message - * @param pool_size the size of buffer to save messages - * @param flag the flag of message queue + * @param msgpool is a pointer to the starting address of the memory space you allocated for + * the messagequeue in advance. + * In other words, msgpool is a pointer to the messagequeue buffer of the starting address. * - * @return the operation status, RT_EOK on successful + * @param msg_size is the maximum length of a message in the messagequeue (Unit: Byte). + * + * @param pool_size is the size of the memory space allocated for the messagequeue in advance. + * + * @param flag is the messagequeue flag, which determines the queuing way of how multiple threads wait + * when the messagequeue is not available. + * The messagequeue flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this messagequeue will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_mq_init(rt_mq_t mq, const char *name, @@ -2021,12 +2511,24 @@ rt_err_t rt_mq_init(rt_mq_t mq, } RTM_EXPORT(rt_mq_init); + /** - * This function will detach a message queue object from resource management + * @brief This function will detach a static messagequeue object. + * + * @note This function is used to detach a static messagequeue object which is initialized by rt_mq_init() function. + * By contrast, the rt_mq_delete() function will delete a messagequeue object. + * When the messagequeue is successfully detached, it will resume all suspended threads in the messagequeue list. * - * @param mq the message queue object + * @see rt_mq_delete() * - * @return the operation status, RT_EOK on successful + * @param mq is a pointer to a messagequeue object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the messagequeue detach failed. + * + * @warning This function can ONLY detach a static messagequeue initialized by the rt_mq_init() function. + * If the messagequeue is created by the rt_mq_create() function, you MUST NOT USE this function to detach it, + * and ONLY USE the rt_mq_delete() function to complete the deletion. */ rt_err_t rt_mq_detach(rt_mq_t mq) { @@ -2049,14 +2551,36 @@ RTM_EXPORT(rt_mq_detach); #ifdef RT_USING_HEAP /** - * This function will create a message queue object from system resource + * @brief Creating a messagequeue object. + * + * @note For the messagequeue object, its memory space is allocated automatically. + * By contrast, the rt_mq_init() function will initialize a static messagequeue object. + * + * @see rt_mq_init() + * + * @param name is a pointer that given to the messagequeue. + * + * @param msg_size is the maximum length of a message in the messagequeue (Unit: Byte). + * + * @param max_msgs is the maximum number of messages in the messagequeue. + * + * @param flag is the messagequeue flag, which determines the queuing way of how multiple threads wait + * when the messagequeue is not available. + * The messagequeue flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. * - * @param name the name of message queue - * @param msg_size the size of message - * @param max_msgs the maximum number of message in queue - * @param flag the flag of message queue + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). * - * @return the created message queue, RT_NULL on error happen + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this messagequeue will become non-real-time threads. + * + * @return Return a pointer to the messagequeue object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can NOT be called in interrupt context. You can use macor RT_DEBUG_NOT_IN_INTERRUPT to check it. */ rt_mq_t rt_mq_create(const char *name, rt_size_t msg_size, @@ -2119,12 +2643,25 @@ rt_mq_t rt_mq_create(const char *name, } RTM_EXPORT(rt_mq_create); + /** - * This function will delete a message queue object and release the memory + * @brief This function will delete a messagequeue object and release the memory. + * + * @note This function is used to delete a messagequeue object which is created by the rt_mq_create() function. + * By contrast, the rt_mq_detach() function will detach a static messagequeue object. + * When the messagequeue is successfully deleted, it will resume all suspended threads in the messagequeue list. + * + * @see rt_mq_detach() * - * @param mq the message queue object + * @param mq is a pointer to a messagequeue object to be deleted. * - * @return the error code + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the messagequeue detach failed. + * + * @warning This function can ONLY delete a messagequeue initialized by the rt_mq_create() function. + * If the messagequeue is initialized by the rt_mq_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_mq_detach() function to complete the detachment. + * for example,the rt_mq_create() function, it cannot be called in interrupt context. */ rt_err_t rt_mq_delete(rt_mq_t mq) { @@ -2149,18 +2686,37 @@ rt_err_t rt_mq_delete(rt_mq_t mq) return RT_EOK; } RTM_EXPORT(rt_mq_delete); -#endif +#endif /* RT_USING_HEAP */ + /** - * This function will send a message to message queue object. If the message queue is full, - * current thread will be suspended until timeout. + * @brief This function will send a message to the messagequeue object. If + * there is a thread suspended on the messagequeue, the thread will be + * resumed. + * + * @note When using this function to send a message, if the messagequeue is + * fully used, the current thread will wait for a timeout. If reaching + * the timeout and there is still no space available, the sending + * thread will be resumed and an error code will be returned. By + * contrast, the rt_mq_send() function will return an error code + * immediately without waiting when the messagequeue if fully used. + * + * @see rt_mq_send() * - * @param mq the message queue object - * @param buffer the message - * @param size the size of buffer - * @param timeout the waiting time + * @param mq is a pointer to the messagequeue object to be sent. * - * @return the error code + * @param buffer is the content of the message. + * + * @param size is the length of the message(Unit: Byte). + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the + * operation is successful. If the return value is any other values, + * it means that the messagequeue detach failed. + * + * @warning This function can be called in interrupt context and thread + * context. */ rt_err_t rt_mq_send_wait(rt_mq_t mq, const void *buffer, @@ -2323,15 +2879,28 @@ rt_err_t rt_mq_send_wait(rt_mq_t mq, } RTM_EXPORT(rt_mq_send_wait) + /** - * This function will send a message to message queue object, if there are - * threads suspended on message queue object, it will be waked up. + * @brief This function will send a message to the messagequeue object. + * If there is a thread suspended on the messagequeue, the thread will be resumed. + * + * @note When using this function to send a message, if the messagequeue is fully used, + * the current thread will wait for a timeout. + * By contrast, when the messagequeue is fully used, the rt_mq_send_wait() function will + * return an error code immediately without waiting. + * + * @see rt_mq_send_wait() + * + * @param mq is a pointer to the messagequeue object to be sent. + * + * @param buffer is the content of the message. * - * @param mq the message queue object - * @param buffer the message - * @param size the size of buffer + * @param size is the length of the message(Unit: Byte). * - * @return the error code + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the messagequeue detach failed. + * + * @warning This function can be called in interrupt context and thread context. */ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size) { @@ -2339,16 +2908,24 @@ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size) } RTM_EXPORT(rt_mq_send); + /** - * This function will send an urgent message to message queue object, which - * means the message will be inserted to the head of message queue. If there - * are threads suspended on message queue object, it will be waked up. + * @brief This function will send an urgent message to the messagequeue object. + * + * @note This function is almost the same as the rt_mq_send() function. The only difference is that + * when sending an urgent message, the message is placed at the head of the messagequeue so that + * the recipient can receive the urgent message first. + * + * @see rt_mq_send() + * + * @param mq is a pointer to the messagequeue object to be sent. * - * @param mq the message queue object - * @param buffer the message - * @param size the size of buffer + * @param buffer is the content of the message. * - * @return the error code + * @param size is the length of the message(Unit: Byte). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. */ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) { @@ -2431,17 +3008,25 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) } RTM_EXPORT(rt_mq_urgent); + /** - * This function will receive a message from message queue object, if there is - * no message in message queue object, the thread shall wait for a specified - * time. + * @brief This function will receive a message from message queue object, + * if there is no message in messagequeue object, the thread shall wait for a specified time. + * + * @note Only when there is mail in the mailbox, the receiving thread can get the mail immediately and return RT_EOK, + * otherwise the receiving thread will be suspended until timeout. + * If the mail is not received within the specified time, it will return -RT_ETIMEOUT. + * + * @param mq is a pointer to the messagequeue object to be received. * - * @param mq the message queue object - * @param buffer the received message will be saved in - * @param size the size of buffer - * @param timeout the waiting time + * @param buffer is the content of the message. * - * @return the error code + * @param size is the length of the message(Unit: Byte). + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox release failed. */ rt_err_t rt_mq_recv(rt_mq_t mq, void *buffer, @@ -2593,15 +3178,20 @@ rt_err_t rt_mq_recv(rt_mq_t mq, } RTM_EXPORT(rt_mq_recv); + /** - * This function can get or set some extra attributions of a message queue - * object. + * @brief This function will set some extra attributions of a messagequeue object. + * + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the messagequeue. * - * @param mq the message queue object - * @param cmd the execution command - * @param arg the execution argument + * @param mq is a pointer to a messagequeue object. * - * @return the error code + * @param cmd is a command used to configure some attributions of the messagequeue. + * + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) { @@ -2653,6 +3243,8 @@ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mq_control); -#endif /* end of RT_USING_MESSAGEQUEUE */ + +/**@}*/ +#endif /* RT_USING_MESSAGEQUEUE */ /**@}*/ @@ -39,9 +39,7 @@ void rt_interrupt_leave_sethook(void (*hook)(void)) { rt_interrupt_leave_hook = hook; } -#endif - -/* #define IRQ_DEBUG */ +#endif /* RT_USING_HOOK */ /** * @addtogroup Kernel @@ -53,7 +51,7 @@ void rt_interrupt_leave_sethook(void (*hook)(void)) #define rt_interrupt_nest rt_cpu_self()->irq_nest #else volatile rt_uint8_t rt_interrupt_nest = 0; -#endif +#endif /* RT_USING_SMP */ /** * This function will be invoked by BSP, when enter interrupt service routine @@ -91,8 +89,8 @@ void rt_interrupt_leave(void) rt_interrupt_nest)); level = rt_hw_interrupt_disable(); - rt_interrupt_nest --; RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,()); + rt_interrupt_nest --; rt_hw_interrupt_enable(level); } RTM_EXPORT(rt_interrupt_leave); diff --git a/src/kservice.c b/src/kservice.c index 7ed05b6651..128a9f4f54 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -25,7 +25,7 @@ #ifdef RT_USING_MODULE #include <dlmodule.h> -#endif +#endif /* RT_USING_MODULE */ /* use precision */ #define RT_PRINTF_PRECISION @@ -194,7 +194,7 @@ RT_WEAK void *rt_memset(void *s, int c, rt_ubase_t count) #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL -#endif +#endif /* RT_KSERVICE_USING_TINY_SIZE */ } RTM_EXPORT(rt_memset); @@ -277,7 +277,7 @@ RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count) #undef BIGBLOCKSIZE #undef LITTLEBLOCKSIZE #undef TOO_SMALL -#endif +#endif /* RT_KSERVICE_USING_TINY_SIZE */ } RTM_EXPORT(rt_memcpy); @@ -509,7 +509,7 @@ rt_size_t rt_strlen(const char *s) } RTM_EXPORT(rt_strlen); -#endif /*RT_KSERVICE_USING_STDLIB*/ +#endif /* RT_KSERVICE_USING_STDLIB */ #ifdef RT_USING_HEAP /** @@ -532,10 +532,10 @@ char *rt_strdup(const char *s) return tmp; } RTM_EXPORT(rt_strdup); -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION char *strdup(const char *s) __attribute__((alias("rt_strdup"))); #endif -#endif +#endif /* RT_USING_HEAP */ /** * This function will show the version of rt-thread rtos @@ -591,7 +591,7 @@ rt_inline int divide(long *n, int base) return res; } -#endif +#endif /* RT_PRINTF_LONGLONG */ rt_inline int skip_atoi(const char **s) { @@ -617,7 +617,7 @@ static char *print_number(char *buf, long long num, #else long num, -#endif +#endif /* RT_PRINTF_LONGLONG */ int base, int s, int precision, @@ -629,18 +629,18 @@ static char *print_number(char *buf, long long num, #else long num, -#endif +#endif /* RT_PRINTF_LONGLONG */ int base, int s, int type) -#endif +#endif /* RT_PRINTF_PRECISION */ { char c, sign; #ifdef RT_PRINTF_LONGLONG char tmp[32]; #else char tmp[16]; -#endif +#endif /* RT_PRINTF_LONGLONG */ int precision_bak = precision; const char *digits; static const char small_digits[] = "0123456789abcdef"; @@ -679,7 +679,7 @@ static char *print_number(char *buf, else if (base == 8) size--; } -#endif +#endif /* RT_PRINTF_SPECIAL */ i = 0; if (num == 0) @@ -696,7 +696,7 @@ static char *print_number(char *buf, size -= precision; #else size -= i; -#endif +#endif /* RT_PRINTF_PRECISION */ if (!(type & (ZEROPAD | LEFT))) { @@ -742,7 +742,7 @@ static char *print_number(char *buf, ++ buf; } } -#endif +#endif /* RT_PRINTF_SPECIAL */ /* no align to the left */ if (!(type & LEFT)) @@ -762,7 +762,7 @@ static char *print_number(char *buf, *buf = '0'; ++ buf; } -#endif +#endif /* RT_PRINTF_PRECISION */ /* put number in the temporary buffer */ while (i-- > 0 && (precision_bak != 0)) @@ -791,7 +791,7 @@ rt_int32_t rt_vsnprintf(char *buf, unsigned long long num; #else rt_uint32_t num; -#endif +#endif /* RT_PRINTF_LONGLONG */ int i, len; char *str, *end, c; const char *s; @@ -803,7 +803,7 @@ rt_int32_t rt_vsnprintf(char *buf, #ifdef RT_PRINTF_PRECISION int precision; /* min. # of digits for integers and max for a string */ -#endif +#endif /* RT_PRINTF_PRECISION */ str = buf; end = buf + size; @@ -870,14 +870,14 @@ rt_int32_t rt_vsnprintf(char *buf, } if (precision < 0) precision = 0; } -#endif +#endif /* RT_PRINTF_PRECISION */ /* get the conversion qualifier */ qualifier = 0; #ifdef RT_PRINTF_LONGLONG if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') #else if (*fmt == 'h' || *fmt == 'l') -#endif +#endif /* RT_PRINTF_LONGLONG */ { qualifier = *fmt; ++ fmt; @@ -887,7 +887,7 @@ rt_int32_t rt_vsnprintf(char *buf, qualifier = 'L'; ++ fmt; } -#endif +#endif /* RT_PRINTF_LONGLONG */ } /* the default base */ @@ -925,7 +925,7 @@ rt_int32_t rt_vsnprintf(char *buf, for (len = 0; (len != field_width) && (s[len] != '\0'); len++); #ifdef RT_PRINTF_PRECISION if (precision > 0 && len > precision) len = precision; -#endif +#endif /* RT_PRINTF_PRECISION */ if (!(flags & LEFT)) { @@ -964,7 +964,7 @@ rt_int32_t rt_vsnprintf(char *buf, str = print_number(str, end, (long)va_arg(args, void *), 16, field_width, flags); -#endif +#endif /* RT_PRINTF_PRECISION */ continue; case '%': @@ -1010,7 +1010,7 @@ rt_int32_t rt_vsnprintf(char *buf, else if (qualifier == 'l') #else if (qualifier == 'l') -#endif +#endif /* RT_PRINTF_LONGLONG */ { num = va_arg(args, rt_uint32_t); if (flags & SIGN) num = (rt_int32_t)num; @@ -1029,7 +1029,7 @@ rt_int32_t rt_vsnprintf(char *buf, str = print_number(str, end, num, base, field_width, precision, flags); #else str = print_number(str, end, num, base, field_width, flags); -#endif +#endif /* RT_PRINTF_PRECISION */ } if (size > 0) @@ -1152,7 +1152,7 @@ rt_device_t rt_console_set_device(const char *name) return old_device; } RTM_EXPORT(rt_console_set_device); -#endif +#endif /* RT_USING_DEVICE */ RT_WEAK void rt_hw_console_output(const char *str) { @@ -1176,15 +1176,11 @@ void rt_kputs(const char *str) } else { - rt_uint16_t old_flag = _console_device->open_flag; - - _console_device->open_flag |= RT_DEVICE_FLAG_STREAM; rt_device_write(_console_device, 0, str, rt_strlen(str)); - _console_device->open_flag = old_flag; } #else rt_hw_console_output(str); -#endif +#endif /* RT_USING_DEVICE */ } /** @@ -1214,19 +1210,15 @@ RT_WEAK void rt_kprintf(const char *fmt, ...) } else { - rt_uint16_t old_flag = _console_device->open_flag; - - _console_device->open_flag |= RT_DEVICE_FLAG_STREAM; rt_device_write(_console_device, 0, rt_log_buf, length); - _console_device->open_flag = old_flag; } #else rt_hw_console_output(rt_log_buf); -#endif +#endif /* RT_USING_DEVICE */ va_end(args); } RTM_EXPORT(rt_kprintf); -#endif +#endif /* RT_USING_CONSOLE */ #ifdef RT_USING_HEAP /** @@ -1238,7 +1230,7 @@ RTM_EXPORT(rt_kprintf); * * @return the allocated memory block on successful, otherwise returns RT_NULL */ -void *rt_malloc_align(rt_size_t size, rt_size_t align) +RT_WEAK void *rt_malloc_align(rt_size_t size, rt_size_t align) { void *ptr; void *align_ptr; @@ -1284,7 +1276,7 @@ RTM_EXPORT(rt_malloc_align); * * @param ptr the memory block pointer */ -void rt_free_align(void *ptr) +RT_WEAK void rt_free_align(void *ptr) { void *real_ptr; @@ -1292,7 +1284,7 @@ void rt_free_align(void *ptr) rt_free(real_ptr); } RTM_EXPORT(rt_free_align); -#endif +#endif /* RT_USING_HEAP */ #ifndef RT_USING_CPU_FFS const rt_uint8_t __lowest_bit_bitmap[] = @@ -1340,7 +1332,7 @@ int __rt_ffs(int value) return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25; } -#endif +#endif /* RT_USING_CPU_FFS */ #ifdef RT_DEBUG /* RT_ASSERT(EX)'s hook */ @@ -1377,7 +1369,7 @@ void rt_assert_handler(const char *ex_string, const char *func, rt_size_t line) dlmodule_exit(-1); } else -#endif +#endif /*RT_USING_MODULE*/ { rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line); while (dummy == 0); @@ -52,7 +52,6 @@ #ifndef RT_USING_MEMHEAP_AS_HEAP -/* #define RT_MEM_DEBUG */ #define RT_MEM_STATS #if defined (RT_USING_HEAP) && defined (RT_USING_SMALL_MEM) @@ -90,7 +89,7 @@ void rt_free_sethook(void (*hook)(void *ptr)) /**@}*/ -#endif +#endif /* RT_USING_HOOK */ #define HEAP_MAGIC 0x1ea0 struct heap_mem @@ -100,7 +99,7 @@ struct heap_mem rt_uint16_t used; #ifdef ARCH_CPU_64BIT rt_uint32_t resv; -#endif +#endif /* ARCH_CPU_64BIT */ rt_size_t next, prev; @@ -109,8 +108,8 @@ struct heap_mem rt_uint8_t thread[8]; #else rt_uint8_t thread[4]; /* thread name */ -#endif -#endif +#endif /* ARCH_CPU_64BIT */ +#endif /* RT_USING_MEMTRACE */ }; /** pointer to the heap: for alignment, heap_ptr is now a pointer instead of an array */ @@ -123,7 +122,7 @@ static struct heap_mem *heap_end; #define MIN_SIZE 24 #else #define MIN_SIZE 12 -#endif +#endif /* ARCH_CPU_64BIT */ #define MIN_SIZE_ALIGNED RT_ALIGN(MIN_SIZE, RT_ALIGN_SIZE) #define SIZEOF_STRUCT_MEM RT_ALIGN(sizeof(struct heap_mem), RT_ALIGN_SIZE) @@ -135,7 +134,8 @@ static rt_size_t mem_size_aligned; #ifdef RT_MEM_STATS static rt_size_t used_mem, max_mem; -#endif +#endif /* RT_MEM_STATS */ + #ifdef RT_USING_MEMTRACE rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name) { @@ -151,7 +151,7 @@ rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name) mem->thread[index] = ' '; } } -#endif +#endif /* RT_USING_MEMTRACE */ static void plug_holes(struct heap_mem *mem) { @@ -238,7 +238,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) mem->used = 0; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem, "INIT"); -#endif +#endif /* RT_USING_MEMTRACE */ /* initialize the end of the heap */ heap_end = (struct heap_mem *)&heap_ptr[mem->next]; @@ -248,9 +248,9 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) heap_end->prev = mem_size_aligned + SIZEOF_STRUCT_MEM; #ifdef RT_USING_MEMTRACE rt_mem_setname(heap_end, "INIT"); -#endif +#endif /* RT_USING_MEMTRACE */ - rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO); /* initialize the lowest-free pointer to the start of the heap */ lfree = (struct heap_mem *)heap_ptr; @@ -336,7 +336,7 @@ void *rt_malloc(rt_size_t size) mem2->prev = ptr; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem2, " "); -#endif +#endif /* RT_USING_MEMTRACE */ /* and insert it between mem and mem->next */ mem->next = ptr2; @@ -350,7 +350,7 @@ void *rt_malloc(rt_size_t size) used_mem += (size + SIZEOF_STRUCT_MEM); if (max_mem < used_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ } else { @@ -366,7 +366,7 @@ void *rt_malloc(rt_size_t size) used_mem += mem->next - ((rt_uint8_t *)mem - heap_ptr); if (max_mem < used_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ } /* set memory block magic */ mem->magic = HEAP_MAGIC; @@ -375,7 +375,7 @@ void *rt_malloc(rt_size_t size) rt_mem_setname(mem, rt_thread_self()->name); else rt_mem_setname(mem, "NONE"); -#endif +#endif /* RT_USING_MEMTRACE */ if (mem == lfree) { @@ -473,7 +473,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize) /* split memory block */ #ifdef RT_MEM_STATS used_mem -= (size - newsize); -#endif +#endif /* RT_MEM_STATS */ ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; mem2 = (struct heap_mem *)&heap_ptr[ptr2]; @@ -483,7 +483,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize) mem2->prev = ptr; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem2, " "); -#endif +#endif /* RT_USING_MEMTRACE */ mem->next = ptr2; if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM) { @@ -597,7 +597,7 @@ void rt_free(void *rmem) mem->magic = HEAP_MAGIC; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem, " "); -#endif +#endif /* RT_USING_MEMTRACE */ if (mem < lfree) { @@ -607,7 +607,7 @@ void rt_free(void *rmem) #ifdef RT_MEM_STATS used_mem -= (mem->next - ((rt_uint8_t *)mem - heap_ptr)); -#endif +#endif /* RT_MEM_STATS */ /* finally, see if prev or next are free also */ plug_holes(mem); @@ -706,12 +706,12 @@ int memtrace(int argc, char **argv) return 0; } MSH_CMD_EXPORT(memtrace, dump memory trace information); -#endif /* end of RT_USING_MEMTRACE */ -#endif /* end of RT_USING_FINSH */ +#endif /* RT_USING_MEMTRACE */ +#endif /* RT_USING_FINSH */ -#endif +#endif /* defined (RT_USING_HEAP) && defined (RT_USING_SMALL_MEM) */ /**@}*/ -#endif /* end of RT_USING_HEAP */ -#endif /* end of RT_USING_MEMHEAP_AS_HEAP */ +#endif /* RT_MEM_STATS */ +#endif /* RT_USING_MEMHEAP_AS_HEAP */ diff --git a/src/memheap.c b/src/memheap.c index 63327575cc..d77c95601e 100644 --- a/src/memheap.c +++ b/src/memheap.c @@ -17,6 +17,7 @@ * 2013-05-24 Bernard fix the rt_memheap_realloc issue. * 2013-07-11 Grissiom fix the memory block splitting issue. * 2013-07-15 Grissiom optimize rt_memheap_realloc + * 2021-06-03 Flybreak Fix the crash problem after opening Oz optimization on ac6. */ #include <rthw.h> @@ -41,31 +42,31 @@ rt_inline void rt_memheap_setname(struct rt_memheap_item *item, const char *name) { int index; - rt_uint8_t* ptr; + rt_uint8_t *ptr; - ptr = (rt_uint8_t*)&(item->next_free); - for (index = 0; index < sizeof(void*); index ++) + ptr = (rt_uint8_t *) & (item->next_free); + for (index = 0; index < sizeof(void *); index ++) { if (name[index] == '\0') break; ptr[index] = name[index]; } if (name[index] == '\0') ptr[index] = '\0'; - else + else { - ptr = (rt_uint8_t*)&(item->prev_free); - for (index = 0; index < sizeof(void*) && (index + sizeof(void*))< RT_NAME_MAX; index ++) + ptr = (rt_uint8_t *) & (item->prev_free); + for (index = 0; index < sizeof(void *) && (index + sizeof(void *)) < RT_NAME_MAX; index ++) { - if (name[sizeof(void*) + index] == '\0') break; - ptr[index] = name[sizeof(void*) + index]; + if (name[sizeof(void *) + index] == '\0') break; + ptr[index] = name[sizeof(void *) + index]; } - if (name[sizeof(void*) + index] == '\0') ptr[index] = '\0'; + if (name[sizeof(void *) + index] == '\0') ptr[index] = '\0'; } } -void rt_mem_set_tag(void* ptr, const char* name) +void rt_mem_set_tag(void *ptr, const char *name) { - struct rt_memheap_item* item; + struct rt_memheap_item *item; if (ptr && name) { @@ -73,7 +74,7 @@ void rt_mem_set_tag(void* ptr, const char* name) rt_memheap_setname(item, name); } } -#endif +#endif /* RT_USING_MEMTRACE */ /* * The initialized memory pool will be: @@ -126,7 +127,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap, #ifdef RT_USING_MEMTRACE rt_memset(item->owner_thread_name, ' ', sizeof(item->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ item->next = (struct rt_memheap_item *) ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE); @@ -154,7 +155,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap, item->next_free = item->prev_free = RT_NULL; /* initialize semaphore lock */ - rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_PRIO); RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n", @@ -251,7 +252,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size) #ifdef RT_USING_MEMTRACE rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* break down the block list */ new_ptr->prev = header_ptr; @@ -309,7 +310,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size) rt_memcpy(header_ptr->owner_thread_name, rt_thread_self()->name, sizeof(header_ptr->owner_thread_name)); else rt_memcpy(header_ptr->owner_thread_name, "NONE", sizeof(header_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* release lock */ rt_sem_release(&(heap->lock)); @@ -369,7 +370,8 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) if (newsize > oldsize) { void *new_ptr; - struct rt_memheap_item *next_ptr; + /* Fix the crash problem after opening Oz optimization on ac6 */ + volatile struct rt_memheap_item *next_ptr; /* lock memheap */ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); @@ -437,18 +439,18 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) #ifdef RT_USING_MEMTRACE rt_memset(next_ptr->owner_thread_name, ' ', sizeof(next_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ next_ptr->prev = header_ptr; next_ptr->next = header_ptr->next; - header_ptr->next->prev = next_ptr; - header_ptr->next = next_ptr; + header_ptr->next->prev = (struct rt_memheap_item *)next_ptr; + header_ptr->next = (struct rt_memheap_item *)next_ptr; /* insert next_ptr to free list */ next_ptr->next_free = heap->free_list->next_free; next_ptr->prev_free = heap->free_list; - heap->free_list->next_free->prev_free = next_ptr; - heap->free_list->next_free = next_ptr; + heap->free_list->next_free->prev_free = (struct rt_memheap_item *)next_ptr; + heap->free_list->next_free = (struct rt_memheap_item *)next_ptr; RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x", next_ptr->next_free, next_ptr->prev_free)); @@ -505,7 +507,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) #ifdef RT_USING_MEMTRACE rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* break down the block list */ new_ptr->prev = header_ptr; @@ -658,7 +660,7 @@ void rt_memheap_free(void *ptr) #ifdef RT_USING_MEMTRACE rt_memset(header_ptr->owner_thread_name, ' ', sizeof(header_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* release lock */ rt_sem_release(&(heap->lock)); @@ -666,17 +668,17 @@ void rt_memheap_free(void *ptr) RTM_EXPORT(rt_memheap_free); #ifdef RT_USING_FINSH -static void _memheap_dump_tag(struct rt_memheap_item* item) +static void _memheap_dump_tag(struct rt_memheap_item *item) { - rt_uint8_t name[2 * sizeof(void*)]; - rt_uint8_t* ptr; + rt_uint8_t name[2 * sizeof(void *)]; + rt_uint8_t *ptr; - ptr = (rt_uint8_t*)&(item->next_free); - rt_memcpy(name, ptr, sizeof(void*)); - ptr = (rt_uint8_t*)&(item->prev_free); - rt_memcpy(&name[sizeof(void*)], ptr, sizeof(void*)); + ptr = (rt_uint8_t *) & (item->next_free); + rt_memcpy(name, ptr, sizeof(void *)); + ptr = (rt_uint8_t *) & (item->prev_free); + rt_memcpy(&name[sizeof(void *)], ptr, sizeof(void *)); - rt_kprintf("%.*s", 2 * sizeof(void*), name); + rt_kprintf("%.*s", 2 * sizeof(void *), name); } int rt_memheap_dump(struct rt_memheap *heap) @@ -686,15 +688,15 @@ int rt_memheap_dump(struct rt_memheap *heap) if (heap == RT_NULL) return 0; RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap); - rt_kprintf("\n[%.*s] [0x%08x - 0x%08x]->\n", RT_NAME_MAX, heap->parent.name, - (rt_ubase_t)heap->start_addr, (rt_ubase_t)heap->start_addr + heap->pool_size); + rt_kprintf("\n[%.*s] [0x%08x - 0x%08x]->\n", RT_NAME_MAX, heap->parent.name, + (rt_ubase_t)heap->start_addr, (rt_ubase_t)heap->start_addr + heap->pool_size); rt_kprintf("------------------------------\n"); /* lock memheap */ rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); item = heap->block_list; - end = (struct rt_memheap_item *) ((rt_uint8_t *)heap->start_addr + heap->pool_size - RT_MEMHEAP_SIZE); + end = (struct rt_memheap_item *)((rt_uint8_t *)heap->start_addr + heap->pool_size - RT_MEMHEAP_SIZE); /* for each memory block */ while ((rt_ubase_t)item < ((rt_ubase_t)end)) @@ -730,13 +732,13 @@ int memheaptrace(void) int index; extern int list_memheap(void); - heaps = (struct rt_memheap**)rt_malloc(sizeof(struct rt_memheap*) * count); + heaps = (struct rt_memheap **)rt_malloc(sizeof(struct rt_memheap *) * count); if (heaps == RT_NULL) return 0; list_memheap(); rt_kprintf("memheap header size: %d\n", RT_MEMHEAP_SIZE); - count = rt_object_get_pointers(RT_Object_Class_MemHeap, (rt_object_t*)heaps, count); + count = rt_object_get_pointers(RT_Object_Class_MemHeap, (rt_object_t *)heaps, count); for (index = 0; index < count; index++) { rt_memheap_dump(heaps[index]); @@ -748,13 +750,15 @@ int memheaptrace(void) return 0; } MSH_CMD_EXPORT(memheaptrace, dump memory trace information); -#endif +#endif /* RT_USING_FINSH */ #ifdef RT_USING_MEMHEAP_AS_HEAP static struct rt_memheap _heap; void rt_system_heap_init(void *begin_addr, void *end_addr) { + RT_ASSERT((rt_uint32_t)end_addr > (rt_uint32_t)begin_addr); + /* initialize a default heap in the system */ rt_memheap_init(&_heap, "heap", @@ -814,7 +818,7 @@ void *rt_malloc(rt_size_t size) RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("malloc => 0x%08x : %d", ptr, size)); } -#endif +#endif /* RT_USING_MEMTRACE */ return ptr; } @@ -880,7 +884,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize) RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("realloc => 0x%08x : %d", new_ptr, newsize)); } -#endif +#endif /* RT_USING_MEMTRACE */ return new_ptr; } @@ -910,7 +914,7 @@ void *rt_calloc(rt_size_t count, rt_size_t size) RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("calloc => 0x%08x : %d", ptr, count * size)); } -#endif +#endif /* RT_USING_MEMTRACE */ return ptr; } @@ -930,7 +934,7 @@ void rt_memory_info(rt_uint32_t *total, *max_used = _heap.max_used_size; } -#endif +#endif /* RT_USING_MEMHEAP_AS_HEAP */ #ifdef RT_USING_MEMTRACE @@ -966,15 +970,15 @@ void dump_used_memheap(struct rt_memheap *mh) { /* dump information */ rt_kprintf("[0x%08x - %d - %c%c%c%c] used\n", header_ptr, block_size, - header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], - header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); + header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], + header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); } else { /* dump information */ rt_kprintf("[0x%08x - %d - %c%c%c%c] free\n", header_ptr, block_size, - header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], - header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); + header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], + header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); } /* move to next used memory block */ @@ -1002,8 +1006,8 @@ void memtrace_heap() #ifdef RT_USING_FINSH #include <finsh.h> MSH_CMD_EXPORT(memtrace_heap, dump memory trace for heap); -#endif /* end of RT_USING_FINSH */ +#endif /* RT_USING_FINSH */ -#endif /* end of RT_USING_MEMTRACE */ +#endif /* RT_USING_MEMTRACE */ -#endif /* end of RT_USING_MEMHEAP */ +#endif /* RT_USING_MEMHEAP */ diff --git a/src/mempool.c b/src/mempool.c index 1de48940d7..5ac87d2bc8 100644 --- a/src/mempool.c +++ b/src/mempool.c @@ -54,7 +54,7 @@ void rt_mp_free_sethook(void (*hook)(struct rt_mempool *mp, void *block)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ /** * @addtogroup MM @@ -290,7 +290,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp) return RT_EOK; } RTM_EXPORT(rt_mp_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will allocate a block from memory pool @@ -451,5 +451,4 @@ RTM_EXPORT(rt_mp_free); /**@}*/ -#endif - +#endif /* RT_USING_MEMPOOL */ diff --git a/src/object.c b/src/object.c index 013e2d1e33..ff96037c52 100644 --- a/src/object.c +++ b/src/object.c @@ -20,7 +20,7 @@ #ifdef RT_USING_MODULE #include <dlmodule.h> -#endif +#endif /* RT_USING_MODULE */ /* * define object_info for the number of rt_object_container items. @@ -189,7 +189,7 @@ void rt_object_put_sethook(void (*hook)(struct rt_object *object)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ /** * @addtogroup KernelObject @@ -305,7 +305,7 @@ void rt_object_init(struct rt_object *object, struct rt_object_information *information; #ifdef RT_USING_MODULE struct rt_dlmodule *module = dlmodule_self(); -#endif +#endif /* RT_USING_MODULE */ /* get object information */ information = rt_object_get_information(type); @@ -349,7 +349,7 @@ void rt_object_init(struct rt_object *object, object->module_id = (void *)module; } else -#endif +#endif /* RT_USING_MODULE */ { /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); @@ -403,7 +403,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) struct rt_object_information *information; #ifdef RT_USING_MODULE struct rt_dlmodule *module = dlmodule_self(); -#endif +#endif /* RT_USING_MODULE */ RT_DEBUG_NOT_IN_INTERRUPT; @@ -444,7 +444,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) object->module_id = (void *)module; } else -#endif +#endif /* RT_USING_MODULE */ { /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); @@ -487,7 +487,7 @@ void rt_object_delete(rt_object_t object) /* free the memory of object */ RT_KERNEL_FREE(object); } -#endif +#endif /* RT_USING_HEAP */ /** * This function will judge the object is system object or not. diff --git a/src/scheduler.c b/src/scheduler.c index c03c20d030..353fdad5cb 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -38,19 +38,18 @@ rt_uint32_t rt_thread_ready_priority_group; #if RT_THREAD_PRIORITY_MAX > 32 /* Maximum priority level, 256 */ rt_uint8_t rt_thread_ready_table[32]; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ #ifndef RT_USING_SMP extern volatile rt_uint8_t rt_interrupt_nest; static rt_int16_t rt_scheduler_lock_nest; struct rt_thread *rt_current_thread = RT_NULL; rt_uint8_t rt_current_priority; -#endif /*RT_USING_SMP*/ - -rt_list_t rt_thread_defunct; +#endif /* RT_USING_SMP */ #ifdef RT_USING_HOOK static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to); +static void (*rt_scheduler_switch_hook)(struct rt_thread *tid); /** * @addtogroup Hook @@ -70,19 +69,25 @@ rt_scheduler_sethook(void (*hook)(struct rt_thread *from, struct rt_thread *to)) rt_scheduler_hook = hook; } +void +rt_scheduler_switch_sethook(void (*hook)(struct rt_thread *tid)) +{ + rt_scheduler_switch_hook = hook; +} + /**@}*/ -#endif +#endif /* RT_USING_HOOK */ #ifdef RT_USING_OVERFLOW_CHECK static void _rt_scheduler_stack_check(struct rt_thread *thread) { RT_ASSERT(thread != RT_NULL); -#if defined(ARCH_CPU_STACK_GROWS_UPWARD) +#ifdef ARCH_CPU_STACK_GROWS_UPWARD if (*((rt_uint8_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size - 1)) != '#' || #else if (*((rt_uint8_t *)thread->stack_addr) != '#' || -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ (rt_ubase_t)thread->sp <= (rt_ubase_t)thread->stack_addr || (rt_ubase_t)thread->sp > (rt_ubase_t)thread->stack_addr + (rt_ubase_t)thread->stack_size) @@ -94,7 +99,7 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread) level = rt_hw_interrupt_disable(); while (level); } -#if defined(ARCH_CPU_STACK_GROWS_UPWARD) +#ifdef ARCH_CPU_STACK_GROWS_UPWARD else if ((rt_ubase_t)thread->sp > ((rt_ubase_t)thread->stack_addr + thread->stack_size)) { rt_kprintf("warning: %s stack is close to the top of stack address.\n", @@ -106,9 +111,9 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread) rt_kprintf("warning: %s stack is close to end of stack address.\n", thread->name); } -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ } -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ /* * get the highest priority thread in ready queue @@ -129,7 +134,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; local_highest_ready_priority = __rt_ffs(pcpu->priority_group) - 1; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* get highest ready priority thread */ if (highest_ready_priority < local_highest_ready_priority) @@ -162,7 +167,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* get highest ready priority thread */ highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, @@ -173,7 +178,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) return highest_priority_thread; } -#endif +#endif /* RT_USING_SMP */ /** * @ingroup SystemInit @@ -183,12 +188,12 @@ void rt_system_scheduler_init(void) { #ifdef RT_USING_SMP int cpu; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ register rt_base_t offset; #ifndef RT_USING_SMP rt_scheduler_lock_nest = 0; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("start scheduler: max priority 0x%02x\n", RT_THREAD_PRIORITY_MAX)); @@ -213,9 +218,9 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 rt_memset(pcpu->ready_table, 0, sizeof(pcpu->ready_table)); -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* initialize ready priority group */ rt_thread_ready_priority_group = 0; @@ -223,10 +228,7 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 /* initialize ready table */ rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table)); -#endif - - /* initialize thread defunct */ - rt_list_init(&rt_thread_defunct); +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /** @@ -245,7 +247,7 @@ void rt_system_scheduler_start(void) to_thread->oncpu = rt_hw_cpu_id(); #else rt_current_thread = to_thread; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ rt_schedule_remove_thread(to_thread); to_thread->stat = RT_THREAD_RUNNING; @@ -255,7 +257,7 @@ void rt_system_scheduler_start(void) rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread); #else rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* never come back */ } @@ -319,7 +321,7 @@ void rt_schedule(void) rt_thread_resume(current_thread); } } -#endif +#endif /* RT_USING_SIGNALS */ if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */ { @@ -367,7 +369,9 @@ void rt_schedule(void) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ + + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); rt_hw_context_switch((rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); @@ -396,7 +400,7 @@ void rt_schedule(void) { rt_hw_interrupt_enable(level); } -#endif +#endif /* RT_USING_SIGNALS */ __exit: return ; @@ -404,7 +408,7 @@ __exit: #else /** * This function will perform one schedule. It will select one thread - * with the highest priority level, then switch to it. + * with the highest priority level, and switch to it immediately. */ void rt_schedule(void) { @@ -472,12 +476,14 @@ void rt_schedule(void) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ if (rt_interrupt_nest == 0) { extern void rt_thread_handle_sig(rt_bool_t clean_state); + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (from_thread)); + rt_hw_context_switch((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp); @@ -502,7 +508,7 @@ void rt_schedule(void) { rt_hw_interrupt_enable(level); } -#endif +#endif /* RT_USING_SIGNALS */ goto __exit; } else @@ -527,7 +533,7 @@ void rt_schedule(void) __exit: return; } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /** * This function checks if a scheduling is needed after IRQ context. If yes, @@ -559,7 +565,7 @@ void rt_scheduler_do_irq_switch(void *context) rt_thread_resume(current_thread); } } -#endif +#endif /* RT_USING_SIGNALS */ if (pcpu->irq_switch_flag == 0) { @@ -608,12 +614,14 @@ void rt_scheduler_do_irq_switch(void *context) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n")); current_thread->cpus_lock_nest--; current_thread->scheduler_lock_nest--; + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); + rt_hw_context_switch_interrupt(context, (rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); } @@ -621,7 +629,7 @@ void rt_scheduler_do_irq_switch(void *context) } rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* * This function will insert a thread to system ready queue. The state of @@ -661,7 +669,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread) { #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ rt_thread_ready_priority_group |= thread->number_mask; rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), @@ -675,7 +683,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread) #if RT_THREAD_PRIORITY_MAX > 32 pcpu->ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ pcpu->priority_group |= thread->number_mask; rt_list_insert_before(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), @@ -724,14 +732,14 @@ void rt_schedule_insert_thread(struct rt_thread *thread) /* set priority mask */ #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ rt_thread_ready_priority_group |= thread->number_mask; __exit: /* enable interrupt */ rt_hw_interrupt_enable(temp); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* * This function will remove a thread from system ready queue. @@ -768,7 +776,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else rt_thread_ready_priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } } else @@ -785,7 +793,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else pcpu->priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } } @@ -818,13 +826,13 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else rt_thread_ready_priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /* enable interrupt */ rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /** * This function will lock the thread scheduler. @@ -885,7 +893,7 @@ void rt_enter_critical(void) /* enable interrupt */ rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RTM_EXPORT(rt_enter_critical); /** @@ -959,7 +967,7 @@ void rt_exit_critical(void) rt_hw_interrupt_enable(level); } } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RTM_EXPORT(rt_exit_critical); /** @@ -975,7 +983,7 @@ rt_uint16_t rt_critical_level(void) return current_thread->critical_lock_nest; #else return rt_scheduler_lock_nest; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ } RTM_EXPORT(rt_critical_level); diff --git a/src/signal.c b/src/signal.c index c2c3e975cb..bb7706d9ef 100644 --- a/src/signal.c +++ b/src/signal.c @@ -20,7 +20,7 @@ #ifndef RT_SIG_INFO_MAX #define RT_SIG_INFO_MAX 32 -#endif +#endif /* RT_SIG_INFO_MAX */ #define DBG_TAG "SIGN" #define DBG_LVL DBG_WARNING @@ -67,7 +67,7 @@ static void _signal_entry(void *parameter) /* return to thread */ tid->sp = tid->sig_ret; tid->sig_ret = RT_NULL; -#endif +#endif /* RT_USING_SMP */ LOG_D("switch back to: 0x%08x\n", tid->sp); tid->stat &= ~RT_THREAD_STAT_SIGNAL; @@ -76,7 +76,7 @@ static void _signal_entry(void *parameter) rt_hw_context_switch_to((rt_base_t)¶meter, tid); #else rt_hw_context_switch_to((rt_ubase_t)&(tid->sp)); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ } /* @@ -153,7 +153,7 @@ static void _signal_deliver(rt_thread_t tid) tid->sig_ret = tid->sp; tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL, (void *)((char *)tid->sig_ret - 32), RT_NULL); -#endif +#endif /* RT_USING_SMP */ rt_hw_interrupt_enable(level); LOG_D("signal stack pointer @ 0x%08x", tid->sp); @@ -204,7 +204,7 @@ void *rt_signal_check(void* context) rt_hw_interrupt_enable(level); return context; } -#endif +#endif /* RT_USING_SMP */ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler) { @@ -586,4 +586,4 @@ int rt_system_signal_init(void) return 0; } -#endif +#endif /* RT_USING_SIGNALS */ diff --git a/src/slab.c b/src/slab.c index 114259002f..ad1dc71811 100644 --- a/src/slab.c +++ b/src/slab.c @@ -61,7 +61,7 @@ /* some statistical variable */ #ifdef RT_MEM_STATS static rt_size_t used_mem, max_mem; -#endif +#endif /* RT_MEM_STATS */ #ifdef RT_USING_HOOK static void (*rt_malloc_hook)(void *ptr, rt_size_t size); @@ -99,7 +99,7 @@ RTM_EXPORT(rt_free_sethook); /**@}*/ -#endif +#endif /* RT_USING_HOOK */ /* * slab allocator implementation @@ -363,7 +363,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) npages = limsize / RT_MM_PAGE_SIZE; /* initialize heap semaphore */ - rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO); RT_DEBUG_LOG(RT_DEBUG_SLAB, ("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n", heap_start, heap_end, limsize, npages)); @@ -516,7 +516,7 @@ void *rt_malloc(rt_size_t size) used_mem += size; if (used_mem > max_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ goto done; } @@ -571,7 +571,7 @@ void *rt_malloc(rt_size_t size) used_mem += z->z_chunksize; if (used_mem > max_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ goto done; } @@ -655,7 +655,7 @@ void *rt_malloc(rt_size_t size) used_mem += z->z_chunksize; if (used_mem > max_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ } done: @@ -790,7 +790,7 @@ void rt_free(void *ptr) (rt_ubase_t)addr, ((rt_ubase_t)(addr) - heap_start) >> RT_MM_PAGE_BITS)); } -#endif +#endif /* RT_DEBUG_SLAB */ kup = btokup((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK); /* release large allocation */ @@ -806,7 +806,7 @@ void rt_free(void *ptr) #ifdef RT_MEM_STATS used_mem -= size * RT_MM_PAGE_SIZE; -#endif +#endif /* RT_MEM_STATS */ rt_sem_release(&heap_sem); RT_DEBUG_LOG(RT_DEBUG_SLAB, @@ -833,7 +833,7 @@ void rt_free(void *ptr) #ifdef RT_MEM_STATS used_mem -= z->z_chunksize; -#endif +#endif /* RT_MEM_STATS */ /* * Bump the number of free chunks. If it becomes non-zero the zone @@ -929,9 +929,9 @@ void list_mem(void) rt_kprintf("maximum allocated memory: %d\n", max_mem); } FINSH_FUNCTION_EXPORT(list_mem, list memory usage information) -#endif -#endif +#endif /* RT_USING_FINSH */ +#endif /* RT_MEM_STATS */ /**@}*/ -#endif +#endif /* defined (RT_USING_HEAP) && defined (RT_USING_SLAB) */ diff --git a/src/thread.c b/src/thread.c index e03c027eff..60e6ab91d1 100644 --- a/src/thread.c +++ b/src/thread.c @@ -32,8 +32,6 @@ #include <rthw.h> #include <rtthread.h> -extern rt_list_t rt_thread_defunct; - #ifdef RT_USING_HOOK static void (*rt_thread_suspend_hook)(rt_thread_t thread); static void (*rt_thread_resume_hook) (rt_thread_t thread); @@ -76,15 +74,15 @@ void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread)) rt_thread_inited_hook = hook; } -#endif +#endif /* RT_USING_HOOK */ /* must be invoke witch rt_hw_interrupt_disable */ -static void _thread_cleanup_execute(rt_thread_t thread) +static void _rt_thread_cleanup_execute(rt_thread_t thread) { register rt_base_t level; #ifdef RT_USING_MODULE struct rt_dlmodule *module = RT_NULL; -#endif +#endif /* RT_USING_MODULE */ level = rt_hw_interrupt_disable(); #ifdef RT_USING_MODULE module = (struct rt_dlmodule*)thread->module_id; @@ -92,18 +90,18 @@ static void _thread_cleanup_execute(rt_thread_t thread) { dlmodule_destroy(module); } -#endif +#endif /* RT_USING_MODULE */ /* invoke thread cleanup */ if (thread->cleanup != RT_NULL) thread->cleanup(thread); #ifdef RT_USING_SIGNALS rt_thread_free_sig(thread); -#endif +#endif /* RT_USING_SIGNALS */ rt_hw_interrupt_enable(level); } -void rt_thread_exit(void) +static void _rt_thread_exit(void) { struct rt_thread *thread; register rt_base_t level; @@ -114,7 +112,7 @@ void rt_thread_exit(void) /* disable interrupt */ level = rt_hw_interrupt_disable(); - _thread_cleanup_execute(thread); + _rt_thread_cleanup_execute(thread); /* remove from schedule */ rt_schedule_remove_thread(thread); @@ -131,7 +129,7 @@ void rt_thread_exit(void) else { /* insert to defunct thread list */ - rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); + rt_thread_defunct_enqueue(thread); } /* switch to next task */ @@ -165,12 +163,12 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, #ifdef ARCH_CPU_STACK_GROWS_UPWARD thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (void *)((char *)thread->stack_addr), - (void *)rt_thread_exit); + (void *)_rt_thread_exit); #else thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)), - (void *)rt_thread_exit); -#endif + (void *)_rt_thread_exit); +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ /* priority init */ RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); @@ -181,7 +179,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, #if RT_THREAD_PRIORITY_MAX > 32 thread->number = 0; thread->high_mask = 0; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* tick init */ thread->init_tick = tick; @@ -200,7 +198,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, thread->scheduler_lock_nest = 0; thread->cpus_lock_nest = 0; thread->critical_lock_nest = 0; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* initialize cleanup function and user data */ thread->cleanup = 0; @@ -221,13 +219,17 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, #ifndef RT_USING_SMP thread->sig_ret = RT_NULL; -#endif +#endif /* RT_USING_SMP */ thread->sig_vectors = RT_NULL; thread->si_list = RT_NULL; -#endif +#endif /* RT_USING_SIGNALS */ #ifdef RT_USING_LWP thread->lwp = RT_NULL; +#endif /* RT_USING_LWP */ + +#ifdef RT_USING_CPU_USAGE + thread->duration_tick = 0; #endif RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); @@ -302,7 +304,7 @@ rt_thread_t rt_thread_self(void) extern rt_thread_t rt_current_thread; return rt_current_thread; -#endif +#endif /* RT_USING_SMP */ } RTM_EXPORT(rt_thread_self); @@ -330,7 +332,7 @@ rt_err_t rt_thread_startup(rt_thread_t thread) thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1L << thread->current_priority; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n", thread->name, thread->init_priority)); @@ -374,22 +376,27 @@ rt_err_t rt_thread_detach(rt_thread_t thread) rt_schedule_remove_thread(thread); } - _thread_cleanup_execute(thread); + _rt_thread_cleanup_execute(thread); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); - /* disable interrupt */ - lock = rt_hw_interrupt_disable(); - /* change stat */ thread->stat = RT_THREAD_CLOSE; - /* detach thread object */ - rt_object_detach((rt_object_t)thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(lock); + if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) + { + rt_object_detach((rt_object_t)thread); + } + else + { + /* disable interrupt */ + lock = rt_hw_interrupt_disable(); + /* insert to defunct thread list */ + rt_thread_defunct_enqueue(thread); + /* enable interrupt */ + rt_hw_interrupt_enable(lock); + } return RT_EOK; } @@ -472,7 +479,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) rt_schedule_remove_thread(thread); } - _thread_cleanup_execute(thread); + _rt_thread_cleanup_execute(thread); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); @@ -484,7 +491,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) thread->stat = RT_THREAD_CLOSE; /* insert to defunct thread list */ - rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); + rt_thread_defunct_enqueue(thread); /* enable interrupt */ rt_hw_interrupt_enable(lock); @@ -492,7 +499,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) return RT_EOK; } RTM_EXPORT(rt_thread_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will let current thread yield processor, and scheduler will @@ -690,7 +697,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; - #endif + #endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* insert thread to schedule queue again */ rt_schedule_insert_thread(thread); @@ -706,7 +713,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; - #endif + #endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /* enable interrupt */ @@ -732,7 +739,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) { rt_err = rt_thread_delete(thread); } - #endif + #endif /* RT_USING_HEAP */ rt_schedule(); return rt_err; } @@ -752,7 +759,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu; break; } - #endif /*RT_USING_SMP*/ + #endif /* RT_USING_SMP */ default: break; @@ -847,12 +854,12 @@ rt_err_t rt_thread_resume(rt_thread_t thread) rt_timer_stop(&thread->thread_timer); - /* enable interrupt */ - rt_hw_interrupt_enable(temp); - /* insert to schedule ready list */ rt_schedule_insert_thread(thread); + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread)); return RT_EOK; } @@ -867,6 +874,7 @@ RTM_EXPORT(rt_thread_resume); void rt_thread_timeout(void *parameter) { struct rt_thread *thread; + register rt_base_t temp; thread = (struct rt_thread *)parameter; @@ -875,6 +883,9 @@ void rt_thread_timeout(void *parameter) RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); + /* disable interrupt */ + temp = rt_hw_interrupt_disable(); + /* set error number */ thread->error = -RT_ETIMEOUT; @@ -884,6 +895,9 @@ void rt_thread_timeout(void *parameter) /* insert to schedule ready list */ rt_schedule_insert_thread(thread); + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + /* do schedule */ rt_schedule(); } diff --git a/src/timer.c b/src/timer.c index 9b0db6c6a5..1c8e70fccc 100644 --- a/src/timer.c +++ b/src/timer.c @@ -31,11 +31,11 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL]; #ifndef RT_TIMER_THREAD_STACK_SIZE #define RT_TIMER_THREAD_STACK_SIZE 512 -#endif +#endif /* RT_TIMER_THREAD_STACK_SIZE */ #ifndef RT_TIMER_THREAD_PRIO #define RT_TIMER_THREAD_PRIO 0 -#endif +#endif /* RT_TIMER_THREAD_PRIO */ /* soft timer status */ static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE; @@ -44,7 +44,7 @@ static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL]; static struct rt_thread timer_thread; ALIGN(RT_ALIGN_SIZE) static rt_uint8_t timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE]; -#endif +#endif /* RT_USING_TIMER_SOFT */ #ifdef RT_USING_HOOK extern void (*rt_object_take_hook)(struct rt_object *object); @@ -81,7 +81,7 @@ void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ static void _rt_timer_init(rt_timer_t timer, void (*timeout)(void *parameter), @@ -171,7 +171,7 @@ void rt_timer_dump(rt_list_t timer_heads[]) } rt_kprintf("\n"); } -#endif +#endif /* RT_DEBUG_TIMER */ /** * @addtogroup Clock @@ -303,7 +303,7 @@ rt_err_t rt_timer_delete(rt_timer_t timer) return RT_EOK; } RTM_EXPORT(rt_timer_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will start the timer @@ -348,7 +348,7 @@ rt_err_t rt_timer_start(rt_timer_t timer) timer_list = rt_soft_timer_list; } else -#endif +#endif /* RT_USING_TIMER_SOFT */ { /* insert timer to system timer list */ timer_list = rt_timer_list; @@ -422,7 +422,7 @@ rt_err_t rt_timer_start(rt_timer_t timer) rt_schedule(); } } -#endif +#endif /* RT_USING_TIMER_SOFT */ return RT_EOK; } @@ -718,7 +718,7 @@ static void rt_thread_timer_entry(void *parameter) rt_soft_timer_check(); } } -#endif +#endif /* RT_USING_TIMER_SOFT */ /** * @ingroup SystemInit @@ -764,7 +764,7 @@ void rt_system_timer_thread_init(void) /* startup */ rt_thread_startup(&timer_thread); -#endif +#endif /* RT_USING_TIMER_SOFT */ } /**@}*/ |
