/** * @ingroup Thread * * This function will perform system background job when system idle. */ void rt_thread_idle_excute(void) { /* check the defunct thread list */ if (!rt_list_isempty(&rt_thread_defunct)) { rt_base_t lock; rt_thread_t thread; #ifdef RT_USING_MODULE rt_module_t module = RT_NULL; #endif RT_DEBUG_NOT_IN_INTERRUPT; /* disable interrupt */ lock = rt_hw_interrupt_disable(); /* re-check whether list is empty */ if (!rt_list_isempty(&rt_thread_defunct)) { /* get defunct thread */ thread = rt_list_entry(rt_thread_defunct.next, struct rt_thread, tlist); #ifdef RT_USING_MODULE /* get thread's parent module */ module = (rt_module_t)thread->module_id; /* if the thread is module's main thread */ if (module != RT_NULL && module->module_thread == thread) { /* detach module's main thread */ module->module_thread = RT_NULL; } #endif /* remove defunct thread */ rt_list_remove(&(thread->tlist)); /* invoke thread cleanup */ if (thread->cleanup != RT_NULL) thread->cleanup(thread); /* if it's a system object, not delete it */ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) { /* enable interrupt */ rt_hw_interrupt_enable(lock); return; } }
/** * This function will remove a rms task from system ready queue. */ void rt_schedule_remove_rms(struct rt_rms *rms) { register rt_base_t temp; RT_ASSERT(rms != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* remove thread from ready list */ rt_list_remove(&(rms->rlist)); if(rt_list_isempty(&(rt_thread_priority_table[rms->thread->current_priority]))) { #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[rms->thread->number] &= ~rms->thread->high_mask; if(rt_thread_ready_table[rms->thread->number] == 0) { rt_thread_ready_priority_group &= ~rms->thread->number_mask; } #else rt_thread_ready_priority_group &= ~rms->thread->number_mask; #endif } /* enable interrupt */ rt_hw_interrupt_enable(temp); }
/** * This function will release a semaphore, if there are threads suspended on * semaphore, it will be waked up. * * @param sem the semaphore object * * @return the error code */ rt_err_t rt_sem_release(rt_sem_t sem) { register rt_base_t temp; register rt_bool_t need_schedule; RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(sem->parent.parent))); need_schedule = RT_FALSE; /* disable interrupt */ temp = rt_hw_interrupt_disable(); RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s releases sem:%s, which value is: %d\n", rt_thread_self()->name, ((struct rt_object *)sem)->name, sem->value)); if (!rt_list_isempty(&sem->parent.suspend_thread)) { /* resume the suspended thread */ rt_ipc_list_resume(&(sem->parent.suspend_thread)); need_schedule = RT_TRUE; } else sem->value ++; /* increase value */ /* enable interrupt */ rt_hw_interrupt_enable(temp); /* resume a thread, re-schedule */ if (need_schedule == RT_TRUE) rt_schedule(); return RT_EOK; }
static void rt_thread_idle_entry(void* parameter) { while (1) { #ifdef RT_USING_HOOK /* if there is an idle thread hook */ if (rt_thread_idle_hook != RT_NULL) rt_thread_idle_hook(); #endif #ifdef RT_USING_HEAP /* check the defunct thread list */ if (!rt_list_isempty(&rt_thread_defunct)) { rt_base_t lock; struct rt_thread* thread = rt_list_entry(rt_thread_defunct.next, struct rt_thread, tlist); /* disable interrupt */ lock = rt_hw_interrupt_disable(); rt_list_remove(&(thread->tlist)); /* enable interrupt */ rt_hw_interrupt_enable(lock); /* release thread's stack */ rt_free(thread->stack_addr); /* delete thread object */ rt_object_delete((rt_object_t)thread); } #endif }
void rt_completion_done(struct rt_completion *completion) { rt_base_t level; RT_ASSERT(completion != RT_NULL); if(completion->flag == RT_COMPLETED) return; level = rt_hw_interrupt_disable(); completion->flag = RT_COMPLETED; if (!rt_list_isempty(&(completion->suspended_list))) { /* there is one thread in suspended list */ struct rt_thread *thread; /* get thread entry */ thread = rt_list_entry(completion->suspended_list.next, struct rt_thread, tlist); /* resume it */ rt_thread_resume(thread); rt_hw_interrupt_enable(level); /* perform a schedule */ rt_schedule(); } else {
rt_err_t rt_completion_wait(struct rt_completion *completion, rt_int32_t timeout) { rt_err_t result; rt_base_t level; rt_thread_t thread; RT_ASSERT(completion != RT_NULL); result = RT_EOK; thread = rt_thread_self(); level = rt_hw_interrupt_disable(); if (completion->flag != RT_COMPLETED) { /* only one thread can suspend on complete */ RT_ASSERT(rt_list_isempty(&(completion->suspended_list))); if (timeout == 0) { result = -RT_ETIMEOUT; goto __exit; } else { /* reset thread error number */ thread->error = RT_EOK; /* suspend thread */ rt_thread_suspend(thread); /* add to suspended list */ rt_list_insert_before(&(completion->suspended_list), &(thread->tlist)); /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; /* start timer */ if (timeout > 0) { /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* do schedule */ rt_schedule(); /* thread is waked up */ result = thread->error; level = rt_hw_interrupt_disable(); /* clean completed flag */ completion->flag = RT_UNCOMPLETED; } } __exit: rt_hw_interrupt_enable(level); return result; }
/** * This function will resume all suspended threads in an IPC object. * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_object_resume_all(struct rt_ipc_object* ipc) { struct rt_thread* thread; register rt_ubase_t temp; /* wakeup all suspend threads */ while (!rt_list_isempty(&(ipc->suspend_thread))) { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* * resume thread * In rt_thread_resume function, it will remove current thread from * suspend list */ rt_thread_resume(thread); /* decrease suspended thread count */ ipc->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } return RT_EOK; }
/* * can interrupt routines */ rt_inline int _can_int_rx(struct rt_can_device *can, struct rt_can_msg *data, int msgs) { int size; struct rt_can_rx_fifo* rx_fifo; RT_ASSERT(can != RT_NULL); size = msgs; rx_fifo = (struct rt_can_rx_fifo*) can->can_rx; RT_ASSERT(rx_fifo != RT_NULL); /* read from software FIFO */ while (msgs) { rt_base_t level; struct rt_can_msg_list *listmsg=RT_NULL; /* disable interrupt */ level = rt_hw_interrupt_disable(); #ifdef RT_CAN_USING_HDR rt_int32_t hdr = data->hdr; if (hdr >=0 && can->hdr && hdr < can->config.maxhdr && !rt_list_isempty(&can->hdr[hdr].list)) { listmsg=rt_list_entry(can->hdr[hdr].list.next, struct rt_can_msg_list, hdrlist); rt_list_remove(&listmsg->list); rt_list_remove(&listmsg->hdrlist); if(can->hdr[hdr].msgs) { can->hdr[hdr].msgs--; } listmsg->owner = RT_NULL; } else if(hdr == -1)
/** * This function will check timer list, if a timeout event happens, the * corresponding timeout function will be invoked. * * @note this function shall be invoked in operating system timer interrupt. */ void rt_timer_check(void) { struct rt_timer *t; rt_tick_t current_tick; register rt_base_t level; RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n")); current_tick = rt_tick_get(); /* disable interrupt */ level = rt_hw_interrupt_disable(); while (!rt_list_isempty(&rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL-1])) { t = rt_list_entry(rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]); /* * It supposes that the new tick shall less than the half duration of * tick max. */ if ((current_tick - t->timeout_tick) < RT_TICK_MAX/2) { RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook, (t)); /* remove timer from timer list firstly */ _rt_timer_remove(t); /* call timeout function */ t->timeout_func(t->parameter); /* re-get tick */ current_tick = rt_tick_get(); RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick)); if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) && (t->parent.flag & RT_TIMER_FLAG_ACTIVATED)) { /* start it */ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; rt_timer_start(t); } else { /* stop timer */ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; } } else break; } /* enable interrupt */ rt_hw_interrupt_enable(level); RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n")); }
static int rt_timer_count_height(struct rt_timer *timer) { int i, cnt = 0; for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++) { if (!rt_list_isempty(&timer->row[i])) cnt++; } return cnt; }
/* the fist timer always in the last row */ static rt_tick_t rt_timer_list_next_timeout(rt_list_t timer_list[]) { struct rt_timer *timer; if (rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) return RT_TICK_MAX; timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]); return timer->timeout_tick; }
/** * This function will delete a memory pool and release the object memory. * * @param mp the memory pool object * * @return RT_EOK */ rt_err_t rt_mp_delete(rt_mp_t mp) { struct rt_thread *thread; register rt_ubase_t temp; RT_DEBUG_NOT_IN_INTERRUPT; /* parameter check */ RT_ASSERT(mp != RT_NULL); /* wake up all suspended threads */ while (!rt_list_isempty(&(mp->suspend_thread))) { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* * resume thread * In rt_thread_resume function, it will remove current thread from suspend * list */ rt_thread_resume(thread); /* decrease suspended thread count */ mp->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } #if defined(RT_USING_MODULE) && defined(RT_USING_SLAB) /* the mp object belongs to an application module */ if (mp->parent.flag & RT_OBJECT_FLAG_MODULE) rt_module_free(mp->parent.module_id, mp->start_address); else #endif /* release allocated room */ rt_free(mp->start_address); /* detach object */ rt_object_delete(&(mp->parent)); return RT_EOK; }
static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe) { if (!rt_list_isempty(&pipe->suspended_write_list)) { rt_thread_t thread; RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_WR); /* get suspended thread */ thread = rt_list_entry(pipe->suspended_write_list.next, struct rt_thread, tlist); /* resume the write thread */ rt_thread_resume(thread); rt_schedule(); }
/** * This function will delete a memory pool and release the object memory. * * @param mp the memory pool object * * @return the operation status, RT_EOK on OK; -RT_ERROR on error * */ rt_err_t rt_mp_delete(rt_mp_t mp) { struct rt_thread* thread; register rt_ubase_t temp; /* parameter check */ RT_ASSERT(mp != RT_NULL); /* wakeup all suspended threads */ while (!rt_list_isempty(&(mp->suspend_thread))) { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* * resume thread * In rt_thread_resume function, it will remove current thread from suspend * list */ rt_thread_resume(thread); /* decrease suspended thread count */ mp->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } /* release allocated room */ rt_free(mp->start_address); /* detach object */ rt_object_delete(&(mp->parent)); return RT_EOK; }
rt_err_t rt_prio_queue_push(struct rt_prio_queue *que, rt_uint8_t prio, void *data, rt_int32_t timeout) { rt_ubase_t level; struct rt_prio_queue_item *item; RT_ASSERT(que); if (prio >= RT_PRIO_QUEUE_PRIO_MAX) return -RT_ERROR; item = rt_mp_alloc(&que->pool, timeout); if (item == RT_NULL) return -RT_ENOMEM; rt_memcpy(item+1, data, que->item_sz); item->next = RT_NULL; level = rt_hw_interrupt_disable(); _do_push(que, prio, item); if (!rt_list_isempty(&(que->suspended_pop_list))) { rt_thread_t thread; /* get thread entry */ thread = rt_list_entry(que->suspended_pop_list.next, struct rt_thread, tlist); /* resume it */ rt_thread_resume(thread); rt_hw_interrupt_enable(level); /* perform a schedule */ rt_schedule(); return RT_EOK; }
/* * This function will remove a thread from system ready queue. * * @param thread the thread to be removed * * @note Please do not invoke this function in user application. */ void rt_schedule_remove_thread(struct rt_thread *thread) { register rt_base_t temp; RT_ASSERT(thread != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable(); #if RT_THREAD_PRIORITY_MAX <= 32 RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%.*s], the priority: %d\n", RT_NAME_MAX, thread->name, thread->current_priority)); #else RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%.*s], the priority: %d 0x%x %d\n", RT_NAME_MAX, thread->name, thread->number, thread->number_mask, thread->high_mask)); #endif /* remove thread from ready list */ rt_list_remove(&(thread->tlist)); if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority]))) { #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] &= ~thread->high_mask; if (rt_thread_ready_table[thread->number] == 0) { rt_thread_ready_priority_group &= ~thread->number_mask; } #else rt_thread_ready_priority_group &= ~thread->number_mask; #endif } /* enable interrupt */ rt_hw_interrupt_enable(temp); }
void rt_prio_queue_detach(struct rt_prio_queue *que) { /* wake up all suspended pop threads, push thread is suspended on mempool. */ while (!rt_list_isempty(&(que->suspended_pop_list))) { rt_thread_t thread; /* disable interrupt */ rt_ubase_t temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(que->suspended_pop_list.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; rt_thread_resume(thread); /* enable interrupt */ rt_hw_interrupt_enable(temp); } rt_mp_detach(&que->pool); }
void rt_timer_check(void) { struct rt_timer *t; rt_tick_t current_tick; register rt_base_t level; #ifdef RT_TIMER_DEBUG rt_kprintf("timer check enter\n"); #endif current_tick = rt_tick_get(); /* disable interrupt */ level = rt_hw_interrupt_disable(); while (!rt_list_isempty(&rt_timer_list)) { t = rt_list_entry(rt_timer_list.next, struct rt_timer, list); /* * It supposes that the new tick shall less than the half duration of tick max. */ if ((current_tick - t->timeout_tick) < RT_TICK_MAX/2) { #ifdef RT_USING_HOOK if (rt_timer_timeout_hook != RT_NULL) rt_timer_timeout_hook(t); #endif /* remove timer from timer list firstly */ rt_list_remove(&(t->list)); /* call timeout function */ t->timeout_func(t->parameter); /* re-get tick */ current_tick = rt_tick_get(); #ifdef RT_TIMER_DEBUG rt_kprintf("current tick: %d\n", current_tick); #endif if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) && (t->parent.flag & RT_TIMER_FLAG_ACTIVATED)) { /* start it */ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; rt_timer_start(t); } else { /* stop timer */ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; } } else break; } /* enable interrupt */ rt_hw_interrupt_enable(level); /* increase soft timer tick */ #ifdef RT_USING_TIMER_SOFT rt_soft_timer_tick_increase ( ); #endif #ifdef RT_TIMER_DEBUG rt_kprintf("timer check leave\n"); #endif }
/** * This function will release a mutex, if there are threads suspended on mutex, * it will be waked up. * * @param mutex the mutex object * * @return the error code */ rt_err_t rt_mutex_release(rt_mutex_t mutex) { register rt_base_t temp; struct rt_thread *thread; rt_bool_t need_schedule; need_schedule = RT_FALSE; /* get current thread */ thread = rt_thread_self(); /* disable interrupt */ temp = rt_hw_interrupt_disable(); RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_release:current thread %s, mutex value: %d, hold: %d\n", thread->name, mutex->value, mutex->hold)); RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mutex->parent.parent))); /* mutex only can be released by owner */ if (thread != mutex->owner) { thread->error = -RT_ERROR; /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_ERROR; } /* decrease hold */ mutex->hold --; /* if no hold */ if (mutex->hold == 0) { /* change the owner thread to original priority */ if (mutex->original_priority != mutex->owner->current_priority) { rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &(mutex->original_priority)); } /* wakeup suspended thread */ if (!rt_list_isempty(&mutex->parent.suspend_thread)) { /* get suspended thread */ thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist); RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_release: resume thread: %s\n", thread->name)); /* set new owner and priority */ mutex->owner = thread; mutex->original_priority = thread->current_priority; mutex->hold ++; /* resume thread */ rt_ipc_list_resume(&(mutex->parent.suspend_thread)); need_schedule = RT_TRUE; } else {
rt_err_t rt_data_queue_push(struct rt_data_queue *queue, const void *data_ptr, rt_size_t data_size, rt_int32_t timeout) { rt_uint16_t mask; rt_ubase_t level; rt_thread_t thread; rt_err_t result; RT_ASSERT(queue != RT_NULL); result = RT_EOK; thread = rt_thread_self(); mask = queue->size - 1; level = rt_hw_interrupt_disable(); while (queue->put_index - queue->get_index == queue->size) { queue->waiting_lwm = RT_TRUE; /* queue is full */ if (timeout == 0) { result = -RT_ETIMEOUT; goto __exit; } /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; /* reset thread error number */ thread->error = RT_EOK; /* suspend thread on the push list */ rt_thread_suspend(thread); rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist)); /* start timer */ if (timeout > 0) { /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* do schedule */ rt_schedule(); /* thread is waked up */ result = thread->error; level = rt_hw_interrupt_disable(); if (result != RT_EOK) goto __exit; } queue->queue[queue->put_index & mask].data_ptr = data_ptr; queue->queue[queue->put_index & mask].data_size = data_size; queue->put_index += 1; if (!rt_list_isempty(&(queue->suspended_pop_list))) { /* there is at least one thread in suspended list */ /* get thread entry */ thread = rt_list_entry(queue->suspended_pop_list.next, struct rt_thread, tlist); /* resume it */ rt_thread_resume(thread); rt_hw_interrupt_enable(level); /* perform a schedule */ rt_schedule(); return result; }