diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/clock.c | 3 | ||||
| -rw-r--r-- | src/ipc.c | 127 | ||||
| -rw-r--r-- | src/kservice.c | 19 | ||||
| -rw-r--r-- | src/mempool.c | 12 | ||||
| -rw-r--r-- | src/object.c | 89 | ||||
| -rw-r--r-- | src/scheduler.c | 33 | ||||
| -rw-r--r-- | src/thread.c | 28 | ||||
| -rw-r--r-- | src/timer.c | 109 |
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 */ @@ -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")); } |
