summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcliff-cmc <[email protected]>2021-02-26 11:09:27 +0800
committerCliff Chen <[email protected]>2021-02-26 11:45:19 +0800
commiteea0c3d74a40f73235da45c6f77e8b411ac94cf2 (patch)
treea6906f1aed7118ab53dbe18f2ee4727a754583af /src
parent1a9ecf27f31277750d92c921b62503f75275e122 (diff)
parentfae0fa8eea4c0e797940bf1eddc8ee6c1711734a (diff)
Add memtrace command for memheap.c
Diffstat (limited to 'src')
-rw-r--r--src/Kconfig14
-rw-r--r--src/SConscript13
-rw-r--r--src/clock.c31
-rw-r--r--src/components.c9
-rw-r--r--src/device.c33
-rw-r--r--src/idle.c79
-rwxr-xr-x[-rw-r--r--]src/ipc.c249
-rw-r--r--src/kservice.c29
-rw-r--r--src/memheap.c121
-rw-r--r--src/mempool.c12
-rw-r--r--src/object.c14
-rw-r--r--src/scheduler.c42
-rw-r--r--src/thread.c209
-rw-r--r--src/timer.c111
14 files changed, 636 insertions, 330 deletions
diff --git a/src/Kconfig b/src/Kconfig
index 63a7a67887..803c827e51 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -270,6 +270,18 @@ menu "Memory Management"
config RT_USING_MEMHEAP_AS_HEAP
bool "Use all of memheap objects as heap"
endif
+
+ config RT_USING_USERHEAP
+ bool "Use user heap"
+ help
+ If this option is selected, please implement these functions:
+ rt_malloc(), rt_malloc_sethook()
+ rt_free(), rt_free_sethook()
+ rt_calloc(), rt_realloc()
+ rt_system_heap_init()
+
+ And if FinSH is used at the same time, please implement list_mem()
+
endchoice
if RT_USING_SMALL_MEM
@@ -294,7 +306,7 @@ menu "Memory Management"
default y if RT_USING_SMALL_MEM
default y if RT_USING_SLAB
default y if RT_USING_MEMHEAP_AS_HEAP
-
+ default y if RT_USING_USERHEAP
endmenu
menu "Kernel Device Object"
diff --git a/src/SConscript b/src/SConscript
index 82c3b8aaf1..68523978d6 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -6,9 +6,6 @@ src = Glob('*.c')
CPPPATH = [RTT_ROOT + '/include']
-if GetDepend('RT_USING_MODULE') == False:
- SrcRemove(src, ['module.c'])
-
if GetDepend('RT_USING_HEAP') == False or GetDepend('RT_USING_SMALL_MEM') == False:
SrcRemove(src, ['mem.c'])
@@ -23,12 +20,20 @@ if GetDepend('RT_USING_MEMHEAP') == False:
if GetDepend('RT_USING_MEMHEAP_AS_HEAP'):
SrcRemove(src, ['mem.c'])
+if GetDepend('RT_USING_USERHEAP'):
+ SrcRemove(src, ['mem.c', 'slab.c'])
+
+if GetDepend('RT_USING_SIGNALS') == False:
+ SrcRemove(src, ['signal.c'])
+
if GetDepend('RT_USING_DEVICE') == False:
SrcRemove(src, ['device.c'])
if GetDepend('RT_USING_SMP') == False:
SrcRemove(src, ['cpu.c'])
-group = DefineGroup('Kernel', src, depend = [''], CPPPATH = CPPPATH)
+CPPDEFINES = ['__RTTHREAD__']
+
+group = DefineGroup('Kernel', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
Return('group')
diff --git a/src/clock.c b/src/clock.c
index 97a09ddeaf..66923e5c00 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -13,6 +13,7 @@
* 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()
*/
#include <rthw.h>
@@ -25,17 +26,6 @@ static rt_tick_t rt_tick = 0;
#endif
/**
- * This function will initialize system tick and set it to zero.
- * @ingroup SystemInit
- *
- * @deprecated since 1.1.0, this function does not need to be invoked
- * in the system initialization.
- */
-void rt_system_tick_init(void)
-{
-}
-
-/**
* @addtogroup Clock
*/
@@ -91,8 +81,7 @@ void rt_tick_increase(void)
thread->stat |= RT_THREAD_STAT_YIELD;
- /* yield */
- rt_thread_yield();
+ rt_schedule();
}
/* check timer */
@@ -128,5 +117,21 @@ rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
}
RTM_EXPORT(rt_tick_from_millisecond);
+/**
+ * This function will provide the passed millisecond from boot.
+ *
+ * @return passed millisecond from boot
+ */
+RT_WEAK rt_tick_t rt_tick_get_millisecond(void)
+{
+#if 1000 % RT_TICK_PER_SECOND == 0u
+ return rt_tick_get() * (1000u / RT_TICK_PER_SECOND);
+#else
+ #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
+}
+
/**@}*/
diff --git a/src/components.c b/src/components.c
index e7824b65ef..8ea5654d0c 100644
--- a/src/components.c
+++ b/src/components.c
@@ -173,19 +173,22 @@ struct rt_thread main_thread;
void main_thread_entry(void *parameter)
{
extern int main(void);
- extern int $Super$$main(void);
#ifdef RT_USING_COMPONENTS_INIT
/* RT-Thread components initialization */
rt_components_init();
#endif
+
#ifdef RT_USING_SMP
rt_hw_secondary_cpu_up();
#endif
/* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
- $Super$$main(); /* for ARMCC. */
-#elif defined(__ICCARM__) || defined(__GNUC__)
+ {
+ extern int $Super$$main(void);
+ $Super$$main(); /* for ARMCC. */
+ }
+#elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__)
main();
#endif
}
diff --git a/src/device.c b/src/device.c
index 32c06b380c..a4f004fb69 100644
--- a/src/device.c
+++ b/src/device.c
@@ -111,38 +111,7 @@ rt_err_t rt_device_init_all(void)
*/
rt_device_t rt_device_find(const char *name)
{
- struct rt_object *object;
- struct rt_list_node *node;
- struct rt_object_information *information;
-
- /* enter critical */
- if (rt_thread_self() != RT_NULL)
- rt_enter_critical();
-
- /* try to find device object */
- information = rt_object_get_information(RT_Object_Class_Device);
- RT_ASSERT(information != RT_NULL);
- for (node = information->object_list.next;
- node != &(information->object_list);
- node = node->next)
- {
- object = rt_list_entry(node, struct rt_object, list);
- if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
- {
- /* leave critical */
- if (rt_thread_self() != RT_NULL)
- rt_exit_critical();
-
- return (rt_device_t)object;
- }
- }
-
- /* leave critical */
- if (rt_thread_self() != RT_NULL)
- rt_exit_critical();
-
- /* not found */
- return RT_NULL;
+ return (rt_device_t)rt_object_find(name, RT_Object_Class_Device);
}
RTM_EXPORT(rt_device_find);
diff --git a/src/idle.c b/src/idle.c
index 99db64f571..aa14552a49 100644
--- a/src/idle.c
+++ b/src/idle.c
@@ -150,82 +150,37 @@ void rt_thread_idle_excute(void)
{
/* Loop until there is no dead thread. So one call to rt_thread_idle_excute
* will do all the cleanups. */
- while (_has_defunct_thread())
+ /* disable interrupt */
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+#ifdef RT_USING_HEAP
+ while (1)
{
rt_base_t lock;
rt_thread_t thread;
-#ifdef RT_USING_MODULE
- struct rt_dlmodule *module = RT_NULL;
-#endif
- RT_DEBUG_NOT_IN_INTERRUPT;
- /* disable interrupt */
lock = rt_hw_interrupt_disable();
- /* re-check whether list is empty */
- if (_has_defunct_thread())
- {
- /* get defunct thread */
- thread = rt_list_entry(rt_thread_defunct.next,
- struct rt_thread,
- tlist);
-#ifdef RT_USING_MODULE
- module = (struct rt_dlmodule*)thread->module_id;
- if (module)
- {
- dlmodule_destroy(module);
- }
-#endif
- /* remove defunct thread */
- rt_list_remove(&(thread->tlist));
-
- /* lock scheduler to prevent scheduling in cleanup function. */
- rt_enter_critical();
-
- /* invoke thread cleanup */
- if (thread->cleanup != RT_NULL)
- thread->cleanup(thread);
-
-#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);
- /* unlock scheduler */
- rt_exit_critical();
-
- /* enable interrupt */
- rt_hw_interrupt_enable(lock);
-
- return;
- }
-
- /* unlock scheduler */
- rt_exit_critical();
- }
- else
+ /* check whether list is empty */
+ if (!_has_defunct_thread())
{
- /* enable interrupt */
rt_hw_interrupt_enable(lock);
-
- /* may the defunct thread list is removed by others, just return */
- return;
+ break;
}
-
- /* enable interrupt */
- rt_hw_interrupt_enable(lock);
-
-#ifdef RT_USING_HEAP
+ /* get defunct thread */
+ thread = rt_list_entry(rt_thread_defunct.next,
+ struct rt_thread,
+ tlist);
+ /* 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);
-#endif
+ rt_hw_interrupt_enable(lock);
}
+#endif
}
extern void rt_system_power_manager(void);
diff --git a/src/ipc.c b/src/ipc.c
index 8e8c4db842..37b05b9ae3 100644..100755
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -34,6 +34,11 @@
* 2013-09-14 Grissiom add an option check in rt_event_recv
* 2018-10-02 Bernard add 64bit support for mailbox
* 2019-09-16 tyx add send wait support for message queue
+ * 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
*/
#include <rtthread.h>
@@ -117,6 +122,9 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list,
rt_list_insert_before(list, &(thread->tlist));
}
break;
+
+ default:
+ break;
}
return RT_EOK;
@@ -184,6 +192,31 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
return RT_EOK;
}
+/**
+ * This function will get the highest priority from the specified
+ * list of threads
+ *
+ * @param list of the threads
+ *
+ * @return the highest priority
+ */
+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
@@ -458,7 +491,17 @@ rt_err_t rt_sem_release(rt_sem_t sem)
need_schedule = RT_TRUE;
}
else
- sem->value ++; /* increase value */
+ {
+ if(sem->value < RT_SEM_VALUE_MAX)
+ {
+ sem->value ++; /* increase value */
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+ }
/* enable interrupt */
rt_hw_interrupt_enable(temp);
@@ -680,12 +723,22 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
if (mutex->owner == thread)
{
- /* it's the same thread */
- mutex->hold ++;
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ /* it's the same thread */
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
}
else
{
+#ifdef RT_USING_SIGNALS
__again:
+#endif /* end of 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.
*/
@@ -697,7 +750,15 @@ __again:
/* set mutex owner and original priority */
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
- mutex->hold ++;
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
}
else
{
@@ -754,8 +815,10 @@ __again:
if (thread->error != RT_EOK)
{
+#ifdef RT_USING_SIGNALS
/* interrupt by signal, try it again */
if (thread->error == -RT_EINTR) goto __again;
+#endif /* end of RT_USING_SIGNALS */
/* return error */
return thread->error;
@@ -792,6 +855,7 @@ 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);
@@ -852,7 +916,31 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
/* set new owner and priority */
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
- mutex->hold ++;
+
+ /* 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 ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
/* resume thread */
rt_ipc_list_resume(&(mutex->parent.suspend_thread));
@@ -861,9 +949,17 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
}
else
{
- /* increase value */
- mutex->value ++;
-
+ if(mutex->value < RT_MUTEX_VALUE_MAX)
+ {
+ /* increase value */
+ mutex->value ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
/* clear owner */
mutex->owner = RT_NULL;
mutex->original_priority = 0xff;
@@ -1080,6 +1176,13 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
status = RT_EOK;
}
}
+ else
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EINVAL;
+ }
/* move node to the next */
n = n->next;
@@ -1177,7 +1280,11 @@ rt_err_t rt_event_recv(rt_event_t event,
/* set received event */
if (recved)
*recved = (event->set & set);
-
+
+ /* fill thread event info */
+ thread->event_set = (event->set & set);
+ thread->event_info = option;
+
/* received event */
if (option & RT_EVENT_FLAG_CLEAR)
event->set &= ~set;
@@ -1186,10 +1293,10 @@ rt_err_t rt_event_recv(rt_event_t event,
{
/* no waiting */
thread->error = -RT_ETIMEOUT;
-
+
/* enable interrupt */
rt_hw_interrupt_enable(level);
-
+
return -RT_ETIMEOUT;
}
else
@@ -1470,7 +1577,6 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
if (mb->entry == mb->size && timeout == 0)
{
rt_hw_interrupt_enable(temp);
-
return -RT_EFULL;
}
@@ -1543,9 +1649,18 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
++ mb->in_offset;
if (mb->in_offset >= mb->size)
mb->in_offset = 0;
- /* increase message entry */
- mb->entry ++;
-
+
+ if(mb->entry < RT_MB_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mb->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
/* resume suspended thread */
if (!rt_list_isempty(&mb->parent.suspend_thread))
{
@@ -1583,6 +1698,71 @@ 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.
+ *
+ * @param mb the mailbox object
+ * @param value the mail
+ *
+ * @return the error code
+ */
+rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value)
+{
+ register rt_ubase_t temp;
+
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent)));
+
+ /* disable interrupt */
+ temp = rt_hw_interrupt_disable();
+
+ if (mb->entry == mb->size)
+ {
+ rt_hw_interrupt_enable(temp);
+ return -RT_EFULL;
+ }
+
+ /* rewind to the previous position */
+ if (mb->out_offset > 0)
+ {
+ mb->out_offset --;
+ }
+ else
+ {
+ mb->out_offset = mb->size - 1;
+ }
+
+ /* set ptr */
+ mb->msg_pool[mb->out_offset] = value;
+
+ /* increase message entry */
+ mb->entry ++;
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&mb->parent.suspend_thread))
+ {
+ rt_ipc_list_resume(&(mb->parent.suspend_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(temp);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(temp);
+
+ return RT_EOK;
+}
+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.
*
@@ -1692,8 +1872,12 @@ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
++ mb->out_offset;
if (mb->out_offset >= mb->size)
mb->out_offset = 0;
+
/* decrease message entry */
- mb->entry --;
+ if(mb->entry > 0)
+ {
+ mb->entry --;
+ }
/* resume suspended thread */
if (!rt_list_isempty(&(mb->suspend_sender_thread)))
@@ -2019,7 +2203,7 @@ rt_err_t rt_mq_send_wait(rt_mq_t mq,
}
/* message queue is full */
- while ((msg = mq->msg_queue_free) == RT_NULL)
+ while ((msg = (struct rt_mq_message *)mq->msg_queue_free) == RT_NULL)
{
/* reset error number in thread */
thread->error = RT_EOK;
@@ -2107,8 +2291,16 @@ rt_err_t rt_mq_send_wait(rt_mq_t mq,
if (mq->msg_queue_head == RT_NULL)
mq->msg_queue_head = msg;
- /* increase message entry */
- mq->entry ++;
+ if(mq->entry < RT_MQ_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mq->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
/* resume suspended thread */
if (!rt_list_isempty(&mq->parent.suspend_thread))
@@ -2207,9 +2399,17 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size)
if (mq->msg_queue_tail == RT_NULL)
mq->msg_queue_tail = msg;
- /* increase message entry */
- mq->entry ++;
-
+ if(mq->entry < RT_MQ_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mq->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
/* resume suspended thread */
if (!rt_list_isempty(&mq->parent.suspend_thread))
{
@@ -2351,7 +2551,10 @@ rt_err_t rt_mq_recv(rt_mq_t mq,
mq->msg_queue_tail = RT_NULL;
/* decrease message entry */
- mq->entry --;
+ if(mq->entry > 0)
+ {
+ mq->entry --;
+ }
/* enable interrupt */
rt_hw_interrupt_enable(temp);
diff --git a/src/kservice.c b/src/kservice.c
index 1705ce5283..423fe3ddb3 100644
--- a/src/kservice.c
+++ b/src/kservice.c
@@ -123,7 +123,7 @@ RTM_EXPORT(_rt_errno);
*
* @return the address of source memory
*/
-void *rt_memset(void *s, int c, rt_ubase_t count)
+RT_WEAK void *rt_memset(void *s, int c, rt_ubase_t count)
{
#ifdef RT_USING_TINY_SIZE
char *xs = (char *)s;
@@ -207,7 +207,7 @@ RTM_EXPORT(rt_memset);
*
* @return the address of destination memory
*/
-void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
+RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
{
#ifdef RT_USING_TINY_SIZE
char *tmp = (char *)dst, *s = (char *)src;
@@ -321,7 +321,7 @@ RTM_EXPORT(rt_memmove);
*
* @return the result
*/
-rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count)
+RT_WEAK rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count)
{
const unsigned char *su1, *su2;
int res = 0;
@@ -456,7 +456,10 @@ RTM_EXPORT(rt_strncmp);
rt_int32_t rt_strcmp(const char *cs, const char *ct)
{
while (*cs && *cs == *ct)
- cs++, ct++;
+ {
+ cs++;
+ ct++;
+ }
return (*cs - *ct);
}
@@ -538,12 +541,12 @@ void rt_show_version(void)
rt_kprintf("- RT - Thread Operating System\n");
rt_kprintf(" / | \\ %d.%d.%d build %s\n",
RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
- rt_kprintf(" 2006 - 2020 Copyright by rt-thread team\n");
+ rt_kprintf(" 2006 - 2021 Copyright by rt-thread team\n");
}
RTM_EXPORT(rt_show_version);
/* private function */
-#define isdigit(c) ((unsigned)((c) - '0') < 10)
+#define _ISDIGIT(c) ((unsigned)((c) - '0') < 10)
#ifdef RT_PRINTF_LONGLONG
rt_inline int divide(long long *n, int base)
@@ -588,7 +591,7 @@ rt_inline int divide(long *n, int base)
rt_inline int skip_atoi(const char **s)
{
register int i = 0;
- while (isdigit(**s))
+ while (_ISDIGIT(**s))
i = i * 10 + *((*s)++) - '0';
return i;
@@ -834,7 +837,7 @@ rt_int32_t rt_vsnprintf(char *buf,
/* get field width */
field_width = -1;
- if (isdigit(*fmt)) field_width = skip_atoi(&fmt);
+ if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt);
else if (*fmt == '*')
{
++ fmt;
@@ -853,7 +856,7 @@ rt_int32_t rt_vsnprintf(char *buf,
if (*fmt == '.')
{
++ fmt;
- if (isdigit(*fmt)) precision = skip_atoi(&fmt);
+ if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt);
else if (*fmt == '*')
{
++ fmt;
@@ -1113,7 +1116,7 @@ RTM_EXPORT(rt_console_get_device);
*
* @param name the name of new console device
*
- * @return the old console device handler
+ * @return the old console device handler on successful, or RT_NULL on failure.
*/
rt_device_t rt_console_set_device(const char *name)
{
@@ -1124,6 +1127,10 @@ rt_device_t rt_console_set_device(const char *name)
/* find new console device */
new_device = rt_device_find(name);
+
+ /* check whether it's a same device */
+ if (new_device == old_device) return RT_NULL;
+
if (new_device != RT_NULL)
{
if (_console_device != RT_NULL)
@@ -1180,7 +1187,7 @@ void rt_kputs(const char *str)
*
* @param fmt the format
*/
-void rt_kprintf(const char *fmt, ...)
+RT_WEAK void rt_kprintf(const char *fmt, ...)
{
va_list args;
rt_size_t length;
diff --git a/src/memheap.c b/src/memheap.c
index aef56e1a74..449e66e975 100644
--- a/src/memheap.c
+++ b/src/memheap.c
@@ -85,6 +85,10 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
item->next_free = item;
item->prev_free = item;
+#ifdef RT_USING_MEMTRACE
+ rt_memset(item->owner_thread_name, ' ', sizeof(item->owner_thread_name));
+#endif
+
item->next = (struct rt_memheap_item *)
((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE);
item->prev = item->next;
@@ -126,8 +130,8 @@ rt_err_t rt_memheap_detach(struct rt_memheap *heap)
RT_ASSERT(heap);
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
RT_ASSERT(rt_object_is_systemobject(&heap->parent));
-
- rt_object_detach(&(heap->lock.parent.parent));
+
+ rt_sem_detach(&heap->lock);
rt_object_detach(&(heap->parent));
/* Return a successful completion. */
@@ -206,6 +210,10 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
+#ifdef RT_USING_MEMTRACE
+ rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name));
+#endif
+
/* break down the block list */
new_ptr->prev = header_ptr;
new_ptr->next = header_ptr->next;
@@ -257,6 +265,13 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
/* Mark the allocated block as not available. */
header_ptr->magic |= RT_MEMHEAP_USED;
+#ifdef RT_USING_MEMTRACE
+ if (rt_thread_self())
+ 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
+
/* release lock */
rt_sem_release(&(heap->lock));
@@ -381,6 +396,10 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
/* put the pool pointer into the new block. */
next_ptr->pool_ptr = heap;
+#ifdef RT_USING_MEMTRACE
+ rt_memset(next_ptr->owner_thread_name, ' ', sizeof(next_ptr->owner_thread_name));
+#endif
+
next_ptr->prev = header_ptr;
next_ptr->next = header_ptr->next;
header_ptr->next->prev = next_ptr;
@@ -445,6 +464,10 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
+#ifdef RT_USING_MEMTRACE
+ rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name));
+#endif
+
/* break down the block list */
new_ptr->prev = header_ptr;
new_ptr->next = header_ptr->next;
@@ -590,6 +613,10 @@ void rt_memheap_free(void *ptr)
header_ptr->next_free, header_ptr->prev_free));
}
+#ifdef RT_USING_MEMTRACE
+ rt_memset(header_ptr->owner_thread_name, ' ', sizeof(header_ptr->owner_thread_name));
+#endif
+
/* release lock */
rt_sem_release(&(heap->lock));
}
@@ -712,6 +739,94 @@ void *rt_calloc(rt_size_t count, rt_size_t size)
}
RTM_EXPORT(rt_calloc);
-#endif
+void rt_memory_info(rt_uint32_t *total,
+ rt_uint32_t *used,
+ rt_uint32_t *max_used)
+{
+ if (total != RT_NULL)
+ *total = _heap.pool_size;
+
+ if (used != RT_NULL)
+ *used = _heap.pool_size - _heap.available_size;
+
+ if (max_used != RT_NULL)
+ *max_used = _heap.max_used_size;
+}
#endif
+
+#ifdef RT_USING_MEMTRACE
+
+void dump_used_memheap(struct rt_memheap *mh)
+{
+ struct rt_memheap_item *header_ptr;
+ rt_uint32_t block_size;
+
+
+ rt_kprintf("\nmemory heap address:\n");
+ rt_kprintf("heap_ptr: 0x%08x\n", mh->start_addr);
+ rt_kprintf("free : 0x%08x\n", mh->available_size);
+ rt_kprintf("max_used: 0x%08x\n", mh->max_used_size);
+ rt_kprintf("size : 0x%08x\n", mh->pool_size);
+
+ rt_kprintf("\n--memory used information --\n");
+
+ header_ptr = mh->block_list;
+ while (header_ptr->next != mh->block_list)
+ {
+ if ((header_ptr->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
+ {
+ rt_kprintf("[0x%08x - incorrect magic: 0x%08x\n", header_ptr, header_ptr->magic);
+ break;
+ }
+
+ /* get current memory block size */
+ block_size = MEMITEM_SIZE(header_ptr);
+ if (block_size < 0)
+ break;
+
+ if (RT_MEMHEAP_IS_USED(header_ptr))
+ {
+ /* 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]);
+ }
+ 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]);
+ }
+
+ /* move to next used memory block */
+ header_ptr = header_ptr->next;
+ }
+}
+
+void memtrace_heap()
+{
+ struct rt_object_information *info;
+ struct rt_list_node *list;
+ struct rt_memheap *mh;
+ struct rt_list_node *node;
+
+ info = rt_object_get_information(RT_Object_Class_MemHeap);
+ list = &info->object_list;
+
+ for (node = list->next; node != list; node = node->next)
+ {
+ mh = (struct rt_memheap *)rt_list_entry(node, struct rt_object, list);
+ dump_used_memheap(mh);
+ }
+}
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+MSH_CMD_EXPORT(memtrace_heap, dump memory trace for heap);
+#endif /* end of RT_USING_FINSH */
+
+#endif /* end of RT_USING_MEMTRACE */
+
+#endif /* end of RT_USING_MEMHEAP */
diff --git a/src/mempool.c b/src/mempool.c
index 00471efb35..db614032aa 100644
--- a/src/mempool.c
+++ b/src/mempool.c
@@ -134,7 +134,7 @@ RTM_EXPORT(rt_mp_init);
rt_err_t rt_mp_detach(struct rt_mempool *mp)
{
struct rt_thread *thread;
- register rt_ubase_t temp;
+ register rt_ubase_t level;
/* parameter check */
RT_ASSERT(mp != RT_NULL);
@@ -145,7 +145,7 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp)
while (!rt_list_isempty(&(mp->suspend_thread)))
{
/* disable interrupt */
- temp = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
@@ -160,7 +160,7 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp)
rt_thread_resume(thread);
/* enable interrupt */
- rt_hw_interrupt_enable(temp);
+ rt_hw_interrupt_enable(level);
}
/* detach object */
@@ -250,7 +250,7 @@ RTM_EXPORT(rt_mp_create);
rt_err_t rt_mp_delete(rt_mp_t mp)
{
struct rt_thread *thread;
- register rt_ubase_t temp;
+ register rt_ubase_t level;
RT_DEBUG_NOT_IN_INTERRUPT;
@@ -263,7 +263,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp)
while (!rt_list_isempty(&(mp->suspend_thread)))
{
/* disable interrupt */
- temp = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
@@ -278,7 +278,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp)
rt_thread_resume(thread);
/* enable interrupt */
- rt_hw_interrupt_enable(temp);
+ rt_hw_interrupt_enable(level);
}
/* release allocated room */
diff --git a/src/object.c b/src/object.c
index 6866d805ca..56263618b3 100644
--- a/src/object.c
+++ b/src/object.c
@@ -192,18 +192,6 @@ void rt_object_put_sethook(void (*hook)(struct rt_object *object))
#endif
/**
- * @ingroup SystemInit
- *
- * This function will initialize system object management.
- *
- * @deprecated since 0.3.0, this function does not need to be invoked
- * in the system initialization.
- */
-void rt_system_object_init(void)
-{
-}
-
-/**
* @addtogroup KernelObject
*/
@@ -485,7 +473,7 @@ void rt_object_delete(rt_object_t object)
RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
/* reset object type */
- object->type = 0;
+ object->type = RT_Object_Class_Null;
/* lock interrupt */
temp = rt_hw_interrupt_disable();
diff --git a/src/scheduler.c b/src/scheduler.c
index 6baaa9627a..06f305ea0b 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -33,10 +33,6 @@
#include <rtthread.h>
#include <rthw.h>
-#ifdef RT_USING_SMP
-rt_hw_spinlock_t _rt_critical_lock;
-#endif /*RT_USING_SMP*/
-
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
rt_uint32_t rt_thread_ready_priority_group;
#if RT_THREAD_PRIORITY_MAX > 32
@@ -47,7 +43,7 @@ rt_uint8_t rt_thread_ready_table[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;
+struct rt_thread *rt_current_thread = RT_NULL;
rt_uint8_t rt_current_priority;
#endif /*RT_USING_SMP*/
@@ -94,12 +90,7 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread)
rt_ubase_t level;
rt_kprintf("thread:%s stack overflow\n", thread->name);
-#ifdef RT_USING_FINSH
- {
- extern long list_thread(void);
- list_thread();
- }
-#endif
+
level = rt_hw_interrupt_disable();
while (level);
}
@@ -350,9 +341,9 @@ void rt_schedule(void)
}
else
{
- current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
rt_schedule_insert_thread(current_thread);
}
+ current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
}
to_thread->oncpu = cpu_id;
if (to_thread != current_thread)
@@ -448,9 +439,9 @@ void rt_schedule(void)
}
else
{
- rt_current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
need_insert_from_thread = 1;
}
+ rt_current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
}
if (to_thread != rt_current_thread)
@@ -599,9 +590,9 @@ void rt_scheduler_do_irq_switch(void *context)
}
else
{
- current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
rt_schedule_insert_thread(current_thread);
}
+ current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
}
to_thread->oncpu = cpu_id;
if (to_thread != current_thread)
@@ -788,7 +779,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread)
{
#if RT_THREAD_PRIORITY_MAX > 32
pcpu->ready_table[thread->number] &= ~thread->high_mask;
- if (rt_thread_ready_table[thread->number] == 0)
+ if (pcpu->ready_table[thread->number] == 0)
{
pcpu->priority_group &= ~thread->number_mask;
}
@@ -851,7 +842,7 @@ void rt_enter_critical(void)
if (!current_thread)
{
rt_hw_local_irq_enable(level);
- return ;
+ return;
}
/*
@@ -859,12 +850,15 @@ void rt_enter_critical(void)
* enough and does not check here
*/
- /* lock scheduler for all cpus */
- if (current_thread->critical_lock_nest == 0)
{
- rt_hw_spin_lock(&_rt_critical_lock);
+ register rt_uint16_t lock_nest = current_thread->cpus_lock_nest;
+ current_thread->cpus_lock_nest++;
+ if (lock_nest == 0)
+ {
+ current_thread->scheduler_lock_nest ++;
+ rt_hw_spin_lock(&_cpus_lock);
+ }
}
-
/* critical for local cpu */
current_thread->critical_lock_nest ++;
@@ -910,16 +904,18 @@ void rt_exit_critical(void)
if (!current_thread)
{
rt_hw_local_irq_enable(level);
- return ;
+ return;
}
current_thread->scheduler_lock_nest --;
current_thread->critical_lock_nest --;
- if (current_thread->critical_lock_nest == 0)
+ current_thread->cpus_lock_nest--;
+ if (current_thread->cpus_lock_nest == 0)
{
- rt_hw_spin_unlock(&_rt_critical_lock);
+ current_thread->scheduler_lock_nest --;
+ rt_hw_spin_unlock(&_cpus_lock);
}
if (current_thread->scheduler_lock_nest <= 0)
diff --git a/src/thread.c b/src/thread.c
index 715596b132..2681eca59f 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -26,6 +26,7 @@
* bug when thread has not startup.
* 2018-11-22 Jesven yield is same to rt_schedule
* add support for tasks bound to cpu
+ * 2021-02-24 Meco Man rearrange rt_thread_control() - schedule the thread when close it
*/
#include <rthw.h>
@@ -77,6 +78,31 @@ void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread))
#endif
+/* must be invoke witch rt_hw_interrupt_disable */
+static void _thread_cleanup_execute(rt_thread_t thread)
+{
+ register rt_base_t level;
+#ifdef RT_USING_MODULE
+ struct rt_dlmodule *module = RT_NULL;
+#endif
+ level = rt_hw_interrupt_disable();
+#ifdef RT_USING_MODULE
+ module = (struct rt_dlmodule*)thread->module_id;
+ if (module)
+ {
+ dlmodule_destroy(module);
+ }
+#endif
+ /* invoke thread cleanup */
+ if (thread->cleanup != RT_NULL)
+ thread->cleanup(thread);
+
+#ifdef RT_USING_SIGNALS
+ rt_thread_free_sig(thread);
+#endif
+ rt_hw_interrupt_enable(level);
+}
+
void rt_thread_exit(void)
{
struct rt_thread *thread;
@@ -88,6 +114,8 @@ void rt_thread_exit(void)
/* disable interrupt */
level = rt_hw_interrupt_disable();
+ _thread_cleanup_execute(thread);
+
/* remove from schedule */
rt_schedule_remove_thread(thread);
/* change stat */
@@ -96,8 +124,7 @@ void rt_thread_exit(void)
/* remove it from timer list */
rt_timer_detach(&thread->thread_timer);
- if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
- thread->cleanup == RT_NULL)
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
{
rt_object_detach((rt_object_t)thread);
}
@@ -347,14 +374,15 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
rt_schedule_remove_thread(thread);
}
+ _thread_cleanup_execute(thread);
+
/* release thread timer */
rt_timer_detach(&(thread->thread_timer));
/* change stat */
thread->stat = RT_THREAD_CLOSE;
- if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
- thread->cleanup == RT_NULL)
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
{
rt_object_detach((rt_object_t)thread);
}
@@ -449,6 +477,8 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
rt_schedule_remove_thread(thread);
}
+ _thread_cleanup_execute(thread);
+
/* release thread timer */
rt_timer_detach(&(thread->thread_timer));
@@ -478,7 +508,15 @@ RTM_EXPORT(rt_thread_delete);
*/
rt_err_t rt_thread_yield(void)
{
+ struct rt_thread *thread;
+ rt_base_t lock;
+
+ thread = rt_thread_self();
+ lock = rt_hw_interrupt_disable();
+ thread->remaining_tick = thread->init_tick;
+ thread->stat |= RT_THREAD_STAT_YIELD;
rt_schedule();
+ rt_hw_interrupt_enable(lock);
return RT_EOK;
}
@@ -561,7 +599,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
if (rt_tick_get() - *tick < inc_tick)
{
- *tick = rt_tick_get() - *tick + inc_tick;
+ *tick = *tick + inc_tick - rt_tick_get();
/* suspend thread */
rt_thread_suspend(thread);
@@ -633,75 +671,93 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
switch (cmd)
{
- case RT_THREAD_CTRL_CHANGE_PRIORITY:
- /* disable interrupt */
- temp = rt_hw_interrupt_disable();
-
- /* for ready thread, change queue */
- if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
+ case RT_THREAD_CTRL_CHANGE_PRIORITY:
{
- /* remove thread from schedule queue first */
- rt_schedule_remove_thread(thread);
+ /* disable interrupt */
+ temp = rt_hw_interrupt_disable();
- /* change thread priority */
- thread->current_priority = *(rt_uint8_t *)arg;
+ /* for ready thread, change queue */
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
+ {
+ /* remove thread from schedule queue first */
+ rt_schedule_remove_thread(thread);
- /* recalculate priority attribute */
-#if RT_THREAD_PRIORITY_MAX > 32
- thread->number = thread->current_priority >> 3; /* 5bit */
- thread->number_mask = 1 << thread->number;
- thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
-#else
- thread->number_mask = 1 << thread->current_priority;
-#endif
+ /* change thread priority */
+ thread->current_priority = *(rt_uint8_t *)arg;
+
+ /* recalculate priority attribute */
+ #if RT_THREAD_PRIORITY_MAX > 32
+ thread->number = thread->current_priority >> 3; /* 5bit */
+ thread->number_mask = 1 << thread->number;
+ thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
+ #else
+ thread->number_mask = 1 << thread->current_priority;
+ #endif
+
+ /* insert thread to schedule queue again */
+ rt_schedule_insert_thread(thread);
+ }
+ else
+ {
+ thread->current_priority = *(rt_uint8_t *)arg;
- /* insert thread to schedule queue again */
- rt_schedule_insert_thread(thread);
+ /* recalculate priority attribute */
+ #if RT_THREAD_PRIORITY_MAX > 32
+ thread->number = thread->current_priority >> 3; /* 5bit */
+ thread->number_mask = 1 << thread->number;
+ thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
+ #else
+ thread->number_mask = 1 << thread->current_priority;
+ #endif
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(temp);
+ break;
}
- else
- {
- thread->current_priority = *(rt_uint8_t *)arg;
- /* recalculate priority attribute */
-#if RT_THREAD_PRIORITY_MAX > 32
- thread->number = thread->current_priority >> 3; /* 5bit */
- thread->number_mask = 1 << thread->number;
- thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
-#else
- thread->number_mask = 1 << thread->current_priority;
-#endif
+ case RT_THREAD_CTRL_STARTUP:
+ {
+ return rt_thread_startup(thread);
}
- /* enable interrupt */
- rt_hw_interrupt_enable(temp);
- break;
+ case RT_THREAD_CTRL_CLOSE:
+ {
+ rt_err_t rt_err;
- case RT_THREAD_CTRL_STARTUP:
- return rt_thread_startup(thread);
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
+ {
+ rt_err = rt_thread_detach(thread);
+ }
+ #ifdef RT_USING_HEAP
+ else
+ {
+ rt_err = rt_thread_delete(thread);
+ }
+ #endif
+ rt_schedule();
+ return rt_err;
+ }
-#ifdef RT_USING_HEAP
- case RT_THREAD_CTRL_CLOSE:
- return rt_thread_delete(thread);
-#endif
+ #ifdef RT_USING_SMP
+ case RT_THREAD_CTRL_BIND_CPU:
+ {
+ rt_uint8_t cpu;
-#ifdef RT_USING_SMP
- case RT_THREAD_CTRL_BIND_CPU:
- {
- rt_uint8_t cpu;
+ if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
+ {
+ /* we only support bind cpu before started phase. */
+ return RT_ERROR;
+ }
- if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
- {
- /* we only support bind cpu before started phase. */
- return RT_ERROR;
+ cpu = (rt_uint8_t)(size_t)arg;
+ thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu;
+ break;
}
+ #endif /*RT_USING_SMP*/
- cpu = (rt_uint8_t)(size_t)arg;
- thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu;
- break;
- }
-#endif /*RT_USING_SMP*/
- default:
- break;
+ default:
+ break;
}
return RT_EOK;
@@ -846,38 +902,7 @@ RTM_EXPORT(rt_thread_timeout);
*/
rt_thread_t rt_thread_find(char *name)
{
- struct rt_object_information *information;
- struct rt_object *object;
- struct rt_list_node *node;
-
- /* enter critical */
- if (rt_thread_self() != RT_NULL)
- rt_enter_critical();
-
- /* try to find device object */
- information = rt_object_get_information(RT_Object_Class_Thread);
- RT_ASSERT(information != RT_NULL);
- for (node = information->object_list.next;
- node != &(information->object_list);
- node = node->next)
- {
- object = rt_list_entry(node, struct rt_object, list);
- if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
- {
- /* leave critical */
- if (rt_thread_self() != RT_NULL)
- rt_exit_critical();
-
- return (rt_thread_t)object;
- }
- }
-
- /* leave critical */
- if (rt_thread_self() != RT_NULL)
- rt_exit_critical();
-
- /* not found */
- return RT_NULL;
+ return (rt_thread_t)rt_object_find(name, RT_Object_Class_Thread);
}
RTM_EXPORT(rt_thread_find);
diff --git a/src/timer.c b/src/timer.c
index 28a5a9e494..d882711151 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -25,6 +25,10 @@
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
#ifdef RT_USING_TIMER_SOFT
+
+#define RT_SOFT_TIMER_IDLE 1
+#define RT_SOFT_TIMER_BUSY 0
+
#ifndef RT_TIMER_THREAD_STACK_SIZE
#define RT_TIMER_THREAD_STACK_SIZE 512
#endif
@@ -33,6 +37,8 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
#define RT_TIMER_THREAD_PRIO 0
#endif
+/* soft timer status */
+static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE;
/* soft timer list */
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
static struct rt_thread timer_thread;
@@ -221,6 +227,8 @@ rt_err_t rt_timer_detach(rt_timer_t timer)
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
+ /* stop timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
@@ -284,6 +292,8 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
+ /* stop timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
@@ -321,7 +331,6 @@ rt_err_t rt_timer_start(rt_timer_t timer)
_rt_timer_remove(timer);
/* change status of timer */
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- rt_hw_interrupt_enable(level);
RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent)));
@@ -332,9 +341,6 @@ rt_err_t rt_timer_start(rt_timer_t timer)
RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2);
timer->timeout_tick = rt_tick_get() + timer->init_tick;
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
-
#ifdef RT_USING_TIMER_SOFT
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
{
@@ -408,7 +414,8 @@ rt_err_t rt_timer_start(rt_timer_t timer)
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
{
/* check whether timer thread is ready */
- if ((timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+ if ((soft_timer_status == RT_SOFT_TIMER_IDLE) &&
+ ((timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
{
/* resume timer thread to check soft timer */
rt_thread_resume(&timer_thread);
@@ -445,13 +452,12 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
+ /* change status */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
- /* change stat */
- timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
-
return RT_EOK;
}
RTM_EXPORT(rt_timer_stop);
@@ -467,10 +473,13 @@ RTM_EXPORT(rt_timer_stop);
*/
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
{
+ register rt_base_t level;
+
/* timer check */
RT_ASSERT(timer != RT_NULL);
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+ level = rt_hw_interrupt_disable();
switch (cmd)
{
case RT_TIMER_CTRL_GET_TIME:
@@ -500,8 +509,12 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
/*timer is stop*/
*(rt_tick_t *)arg = RT_TIMER_FLAG_DEACTIVATED;
}
- break;
+ break;
+
+ default:
+ break;
}
+ rt_hw_interrupt_enable(level);
return RT_EOK;
}
@@ -518,6 +531,7 @@ void rt_timer_check(void)
struct rt_timer *t;
rt_tick_t current_tick;
register rt_base_t level;
+ rt_list_t list = RT_LIST_OBJECT_INIT(list);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
@@ -541,7 +555,12 @@ void rt_timer_check(void)
/* remove timer from timer list firstly */
_rt_timer_remove(t);
-
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
+ {
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ /* add timer to temporary list */
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
/* call timeout function */
t->timeout_func(t->parameter);
@@ -551,6 +570,12 @@ void rt_timer_check(void)
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
+ /* Check whether the timer object is detached or started again */
+ if (rt_list_isempty(&list))
+ {
+ continue;
+ }
+ rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
@@ -558,14 +583,8 @@ void rt_timer_check(void)
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
- else
- {
- /* stop timer */
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- }
}
- else
- break;
+ else break;
}
/* enable interrupt */
@@ -586,26 +605,27 @@ rt_tick_t rt_timer_next_timeout_tick(void)
#ifdef RT_USING_TIMER_SOFT
/**
- * This function will check timer list, if a timeout event happens, the
+ * This function will check software-timer list, if a timeout event happens, the
* corresponding timeout function will be invoked.
*/
void rt_soft_timer_check(void)
{
rt_tick_t current_tick;
- rt_list_t *n;
struct rt_timer *t;
+ register rt_base_t level;
+ rt_list_t list = RT_LIST_OBJECT_INIT(list);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
- current_tick = rt_tick_get();
-
- /* lock scheduler */
- rt_enter_critical();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- for (n = rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next;
- n != &(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]);)
+ while (!rt_list_isempty(&rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
{
- t = rt_list_entry(n, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+ t = rt_list_entry(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+
+ current_tick = rt_tick_get();
/*
* It supposes that the new tick shall less than the half duration of
@@ -615,26 +635,35 @@ void rt_soft_timer_check(void)
{
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
- /* move node to the next */
- n = n->next;
-
/* remove timer from timer list firstly */
_rt_timer_remove(t);
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
+ {
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ /* add timer to temporary list */
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+
+ soft_timer_status = RT_SOFT_TIMER_BUSY;
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
- /* not lock scheduler when performing timeout function */
- rt_exit_critical();
/* call timeout function */
t->timeout_func(t->parameter);
- /* re-get tick */
- current_tick = rt_tick_get();
-
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
- /* lock scheduler */
- rt_enter_critical();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ soft_timer_status = RT_SOFT_TIMER_IDLE;
+ /* Check whether the timer object is detached or started again */
+ if (rt_list_isempty(&list))
+ {
+ continue;
+ }
+ rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
@@ -642,17 +671,11 @@ void rt_soft_timer_check(void)
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
- else
- {
- /* stop timer */
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- }
}
else break; /* not check anymore */
}
-
- /* unlock scheduler */
- rt_exit_critical();
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
}