/** * This function will start the timer * * @param timer the timer to be started * * @return the operation status, RT_EOK on OK, -RT_ERROR on error * */ rt_err_t rt_timer_start(rt_timer_t timer) { struct rt_timer* t; register rt_base_t level; rt_list_t *n, *timer_list; /* timer check */ RT_ASSERT(timer != RT_NULL); if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) return -RT_ERROR; #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(timer->parent)); #endif /* disable interrupt */ level = rt_hw_interrupt_disable(); /* get timeout tick, the max timeout tick shall not great than RT_TICK_MAX/2 */ RT_ASSERT(timer->init_tick < RT_TICK_MAX/2); timer->timeout_tick = rt_tick_get() + timer->init_tick; #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* insert timer to soft timer list */ timer_list = &rt_soft_timer_list; } else #endif { /* insert timer to system timer list */ timer_list = &rt_timer_list; } for (n = timer_list->next; n != timer_list; n = n->next) { t = rt_list_entry(n, struct rt_timer, list); /* * It supposes that the new tick shall less than the half duration of tick max. */ if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX/2) { rt_list_insert_before(n, &(timer->list)); break; } } /* no found suitable position in timer list */ if (n == timer_list) { rt_list_insert_before(n, &(timer->list)); } timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED; /* enable interrupt */ rt_hw_interrupt_enable(level); return -RT_EOK; }
/** * This function will start the timer * * @param timer the timer to be started * * @return the operation status, RT_EOK on OK; RT_ERROR on error * */ rt_err_t rt_timer_start(rt_timer_t timer) { rt_list_t *n; struct rt_timer* t; register rt_base_t level; /* timer check */ RT_ASSERT(timer != RT_NULL); if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) return -RT_ERROR; #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(timer->parent)); #endif timer->timeout_tick = rt_tick_get() + timer->init_tick; /* disable interrupt */ level = rt_hw_interrupt_disable(); if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) {/* insert timer to soft timer list */ for (n = rt_soft_timer_list.next; n != &rt_soft_timer_list; n = n->next) { t = rt_list_entry(n, struct rt_timer, list); if (t->timeout_tick > timer->timeout_tick) { rt_list_insert_before(n, &(timer->list)); break; } } /* no found suitable position in timer list */ if (n == &rt_soft_timer_list) { rt_list_insert_before(n, &(timer->list)); } } else {/* insert timer to system timer list */ /* insert timer to system timer list */ for (n = rt_timer_list.next; n != &rt_timer_list; n = n->next)
/** * This function will take a mutex, if the mutex is unavailable, the * thread shall wait for a specified time. * * @param mutex the mutex object * @param time the waiting time * * @return the error code */ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time) { register rt_base_t temp; struct rt_thread* thread; RT_ASSERT(mutex != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get current thread */ thread = rt_thread_self(); #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mutex->parent.parent)); #endif #ifdef RT_IPC_DEBUG rt_kprintf("mutex_take: current thread %s, mutex value: %d, hold: %d\n", thread->name, mutex->value, mutex->hold); #endif /* reset thread error */ thread->error = RT_EOK; if (mutex->owner == thread) { /* it's the same thread */ mutex->hold ++; } else { /* in initialization status, the value is 1. Therefore, if the * value is great than 1, which indicates the mutex is avaible. */ if (mutex->value > 0) { /* mutex is available */ mutex->value --; /* set mutex owner and original priority */ mutex->owner = thread; mutex->original_priority = thread->current_priority; mutex->hold ++; } else { /* no waiting, return with timeout */ if (time == 0 ) { /* set error as timeout */ thread->error = -RT_ETIMEOUT; /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_ETIMEOUT; } else { /* mutex is unavailable, push to suspend list */ #ifdef RT_IPC_DEBUG rt_kprintf("mutex_take: suspend thread: %s\n", thread->name); #endif /* change the owner thread priority of mutex */ if (thread->current_priority < mutex->owner->current_priority) { /* change the owner thread priority */ rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &thread->current_priority); } /* suspend current thread */ rt_ipc_object_suspend(&(mutex->parent), thread); /* has waiting time, start thread timer */ if (time > 0) { #ifdef RT_IPC_DEBUG rt_kprintf("mutex_take: start the timer of thread:%s\n", thread->name); #endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* do schedule */ rt_schedule(); if (thread->error != RT_EOK) { /* decrease suspended thread count */ rt_ipc_object_decrease(&(mutex->parent)); /* return error */ return thread->error; } else { /* the mutex is taken successfully. */ /* disable interrupt */ temp = rt_hw_interrupt_disable(); } } } } /* enable interrupt */ rt_hw_interrupt_enable(temp); #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(mutex->parent.parent)); #endif return RT_EOK; }
/** * This function will take a semaphore, if the semaphore is unavailable, the * thread shall wait for a specified time. * * @param sem the semaphore object * @param time the waiting time * * @return the error code */ rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time) { register rt_base_t temp; struct rt_thread* thread; RT_ASSERT(sem != RT_NULL); #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(sem->parent.parent)); #endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); #ifdef RT_IPC_DEBUG rt_kprintf("thread %s take sem:%s, which value is: %d\n", rt_thread_self()->name, ((struct rt_object*)sem)->name, sem->value); #endif if (sem->value > 0) { /* semaphore is available */ sem->value --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } else { /* no waiting, return with timeout */ if (time == 0 ) { rt_hw_interrupt_enable(temp); return -RT_ETIMEOUT; } else { /* semaphore is unavailable, push to suspend list */ /* get current thread */ thread = rt_thread_self(); /* reset thread error number */ thread->error = RT_EOK; #ifdef RT_IPC_DEBUG rt_kprintf("sem take: suspend thread - %s\n", thread->name); #endif /* suspend thread */ rt_ipc_object_suspend(&(sem->parent), thread); /* has waiting time, start thread timer */ if (time > 0) { #ifdef RT_IPC_DEBUG rt_kprintf("set thread:%s to timer list\n", thread->name); #endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* do schedule */ rt_schedule(); if (thread->error != RT_EOK) { /* decrease suspended thread count */ rt_ipc_object_decrease(&(sem->parent)); return thread->error; } } } #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(sem->parent.parent)); #endif return RT_EOK; }