summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWangHuachen <[email protected]>2020-11-08 19:30:50 +0800
committerGitHub <[email protected]>2020-11-08 19:30:50 +0800
commit9756c77f0447f9ce4f00a37600298a1f1fd90cda (patch)
tree093247a1719c087dba33783be3a4ee44c1026b2d /src
parent9545529b33cbaae137f1e389dd0e3a5233d516da (diff)
parent4b2b9a87c6f0a87b125e5c5a18bcfcf663de9fbb (diff)
Merge pull request #1 from RT-Thread/master
同步原有仓库
Diffstat (limited to 'src')
-rw-r--r--src/clock.c3
-rw-r--r--src/ipc.c127
-rw-r--r--src/kservice.c19
-rw-r--r--src/mempool.c12
-rw-r--r--src/object.c89
-rw-r--r--src/scheduler.c33
-rw-r--r--src/thread.c28
-rw-r--r--src/timer.c109
8 files changed, 318 insertions, 102 deletions
diff --git a/src/clock.c b/src/clock.c
index 97a09ddeaf..a91cd829b6 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -91,8 +91,7 @@ void rt_tick_increase(void)
thread->stat |= RT_THREAD_STAT_YIELD;
- /* yield */
- rt_thread_yield();
+ rt_schedule();
}
/* check timer */
diff --git a/src/ipc.c b/src/ipc.c
index e6955bae37..454fcb5439 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -34,6 +34,9 @@
* 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
*/
#include <rtthread.h>
@@ -117,6 +120,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;
@@ -458,7 +464,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 +696,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 +723,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 +788,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;
@@ -852,7 +888,15 @@ 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 ++;
+ 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 +905,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 +1132,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 +1236,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,6 +1249,11 @@ 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
{
@@ -1538,9 +1606,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))
{
@@ -2102,8 +2179,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))
@@ -2202,9 +2287,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))
{
diff --git a/src/kservice.c b/src/kservice.c
index 1705ce5283..0a74f05268 100644
--- a/src/kservice.c
+++ b/src/kservice.c
@@ -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);
}
@@ -543,7 +546,7 @@ void rt_show_version(void)
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)
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 4ee2f6a1a1..6866d805ca 100644
--- a/src/object.c
+++ b/src/object.c
@@ -212,7 +212,9 @@ void rt_system_object_init(void)
/**
* This function will return the specified type of object information.
*
- * @param type the type of object
+ * @param type the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ *
* @return the object type information or RT_NULL
*/
struct rt_object_information *
@@ -228,6 +230,77 @@ rt_object_get_information(enum rt_object_class_type type)
RTM_EXPORT(rt_object_get_information);
/**
+ * This function will return the length of object list in object container.
+ *
+ * @param type the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ * @return the length of object list
+ */
+int rt_object_get_length(enum rt_object_class_type type)
+{
+ int count = 0;
+ rt_ubase_t level;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+ if (information == RT_NULL) return 0;
+
+ level = rt_hw_interrupt_disable();
+ /* get the count of objects */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ count ++;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return count;
+}
+RTM_EXPORT(rt_object_get_length);
+
+/**
+ * This function will copy the object pointer of the specified type,
+ * with the maximum size specified by maxlen.
+ *
+ * @param type the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ * @param pointers the pointers will be saved to
+ * @param maxlen the maximum number of pointers can be saved
+ *
+ * @return the copied number of object pointers
+ */
+int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
+{
+ int index = 0;
+ rt_ubase_t level;
+
+ struct rt_object *object;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ if (maxlen <= 0) return 0;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+ if (information == RT_NULL) return 0;
+
+ level = rt_hw_interrupt_disable();
+ /* retrieve pointer of object */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+
+ pointers[index] = object;
+ index ++;
+
+ if (index >= maxlen) break;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return index;
+}
+RTM_EXPORT(rt_object_get_pointers);
+
+/**
* This function will initialize an object and add it to object system
* management.
*
@@ -482,9 +555,10 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type)
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;
+ information = rt_object_get_information((enum rt_object_class_type)type);
+
/* parameter check */
- if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
- return RT_NULL;
+ if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
/* which is invoke in interrupt status */
RT_DEBUG_NOT_IN_INTERRUPT;
@@ -493,14 +567,7 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type)
rt_enter_critical();
/* try to find object */
- if (information == RT_NULL)
- {
- information = rt_object_get_information((enum rt_object_class_type)type);
- RT_ASSERT(information != RT_NULL);
- }
- for (node = information->object_list.next;
- node != &(information->object_list);
- node = node->next)
+ rt_list_for_each(node, &(information->object_list))
{
object = rt_list_entry(node, struct rt_object, list);
if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
diff --git a/src/scheduler.c b/src/scheduler.c
index 6baaa9627a..2250c4a006 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
@@ -350,9 +346,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 +444,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 +595,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 +784,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 +847,7 @@ void rt_enter_critical(void)
if (!current_thread)
{
rt_hw_local_irq_enable(level);
- return ;
+ return;
}
/*
@@ -859,12 +855,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 +909,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 19ab5549c8..49e2022bf7 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -338,6 +338,9 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread));
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
+ return RT_EOK;
+
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
{
/* remove from schedule */
@@ -437,6 +440,9 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE);
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
+ return RT_EOK;
+
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
{
/* remove from schedule */
@@ -472,7 +478,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;
}
@@ -555,7 +569,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);
@@ -673,9 +687,17 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
case RT_THREAD_CTRL_STARTUP:
return rt_thread_startup(thread);
-#ifdef RT_USING_HEAP
case RT_THREAD_CTRL_CLOSE:
- return rt_thread_delete(thread);
+
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
+ {
+ return rt_thread_detach(thread);
+ }
+#ifdef RT_USING_HEAP
+ else
+ {
+ return rt_thread_delete(thread);
+ }
#endif
#ifdef RT_USING_SMP
diff --git a/src/timer.c b/src/timer.c
index 0034f0246c..4b9003794c 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);
@@ -408,7 +418,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 +456,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 +477,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:
@@ -488,7 +501,7 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
case RT_TIMER_CTRL_SET_PERIODIC:
timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
break;
- /* zhaoshimin 20191204 add query the timer state */
+
case RT_TIMER_CTRL_GET_STATE:
if(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
{
@@ -500,8 +513,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 +535,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 +559,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 +574,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;
+ }
+
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
@@ -558,14 +587,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 +609,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,25 +639,34 @@ 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;
+ }
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
@@ -642,17 +675,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"));
}