/** * 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; }
/** * This function will start a thread and put it to system ready queue * * @param thread the thread to be started * * @return the operation status, RT_EOK on OK, -RT_ERROR on error * */ rt_err_t rt_thread_startup(rt_thread_t thread) { /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(thread->stat == RT_THREAD_INIT); /* set current priority to init priority */ thread->current_priority = thread->init_priority; /* calculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1L << thread->number; thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1L << thread->current_priority; #endif RT_DEBUG_LOG(RT_DEBUG_THREAD,\ ("startup a thread:%s with priority:%d\n", thread->name, thread->init_priority)); /* change thread stat */ thread->stat = RT_THREAD_SUSPEND; /* then resume it */ rt_thread_resume(thread); if (rt_thread_self() != RT_NULL) { /* do a scheduling */ rt_schedule(); } return RT_EOK; }
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 {
static void _signal_deliver(rt_thread_t tid) { rt_ubase_t level; /* thread is not interested in pended signals */ if (!(tid->sig_pending & tid->sig_mask)) return; level = rt_hw_interrupt_disable(); if (tid->stat == RT_THREAD_SUSPEND) { /* resume thread to handle signal */ rt_thread_resume(tid); /* add signal state */ tid->stat |= RT_THREAD_STAT_SIGNAL; rt_hw_interrupt_enable(level); /* re-schedule */ rt_schedule(); } else { if (tid == rt_thread_self()) { /* add signal state */ tid->stat |= RT_THREAD_STAT_SIGNAL; rt_hw_interrupt_enable(level); /* do signal action in self thread context */ rt_thread_handle_sig(RT_TRUE); } else if (!(tid->stat & RT_THREAD_STAT_SIGNAL)) { tid->stat |= RT_THREAD_STAT_SIGNAL; /* point to the signal handle entry */ tid->sig_ret = tid->sp; tid->sp = rt_hw_stack_init((void*)_signal_entry, RT_NULL, (void *)((char *)tid->sig_ret - 32), RT_NULL); rt_hw_interrupt_enable(level); dbg_log(DBG_LOG, "signal stack pointer @ 0x%08x\n", tid->sp); /* re-schedule */ rt_schedule(); } else { rt_hw_interrupt_enable(level); } } }
/** * 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; }
/** * This function will resume the first thread in the list of a IPC object: * - remove the thread from suspend queue of IPC object * - put the thread into system ready queue * * @param list the thread list * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list) { struct rt_thread *thread; /* get thread entry */ thread = rt_list_entry(list->next, struct rt_thread, tlist); RT_DEBUG_LOG(RT_DEBUG_IPC, ("resume thread:%s\n", thread->name)); /* resume it */ rt_thread_resume(thread); return RT_EOK; }
/* 线程2入口 */ static void thread2_entry(void* parameter) { /* 延时10个OS Tick */ rt_thread_delay(10); /* 唤醒线程1 */ rt_thread_resume(tid1); rt_kprintf("thread2: to resume thread1\n"); /* 延时10个OS Tick */ rt_thread_delay(10); /* 线程2自动退出 */ }
/** * This function will release a memory block * * @param block the address of memory block to be released * */ void rt_mp_free (void *block) { rt_uint8_t **block_ptr; struct rt_mempool *mp; struct rt_thread *thread; register rt_base_t level; /* get the control block of pool which the block belongs to */ block_ptr = (rt_uint8_t**)((rt_uint8_t*)block - sizeof(rt_uint8_t*)); mp = (struct rt_mempool*) *block_ptr; #ifdef RT_USING_HOOK if (rt_mp_free_hook != RT_NULL) rt_mp_free_hook(mp, block); #endif /* disable interrupt */ level = rt_hw_interrupt_disable(); /* increase the free block count */ mp->block_free_count ++; /* link the block into the block list */ *block_ptr = mp->block_list; mp->block_list = (rt_uint8_t*)block_ptr; if (mp->suspend_thread_count > 0) { /* get the suspended thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error */ thread->error = RT_EOK; /* resume thread */ rt_thread_resume(thread); /* decrease suspended thread count */ mp->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(level); /* do a schedule */ rt_schedule(); return; }
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 resume a thread from an IPC object: * - remove the thread from suspend queue of IPC object * - put the thread into system ready queue * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_object_resume(struct rt_ipc_object* ipc) { struct rt_thread *thread; /* get thread entry */ thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist); #ifdef RT_IPC_DEBUG rt_kprintf("resume thread:%s\n", thread->name); #endif /* resume it */ rt_thread_resume(thread); /* decrease suspended thread count */ ipc->suspend_thread_count --; return RT_EOK; }
/** * 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; }
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); }
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; }
/** * 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) { int row_lvl; rt_list_t *timer_list; register rt_base_t level; rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL]; unsigned int tst_nr; static unsigned int random_nr; /* timer check */ RT_ASSERT(timer != RT_NULL); if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) return -RT_ERROR; RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); /* * 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; /* disable interrupt */ level = rt_hw_interrupt_disable(); #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; } row_head[0] = &timer_list[0]; for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { for (;row_head[row_lvl] != timer_list[row_lvl].prev; row_head[row_lvl] = row_head[row_lvl]->next) { struct rt_timer *t; rt_list_t *p = row_head[row_lvl]->next; /* fix up the entry pointer */ t = rt_list_entry(p, struct rt_timer, row[row_lvl]); /* If we have two timers that timeout at the same time, it's * preferred that the timer inserted early get called early. * So insert the new timer to the end the the some-timeout timer * list. */ if ((t->timeout_tick - timer->timeout_tick) == 0) { continue; } else if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX / 2) { break; } } if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1) row_head[row_lvl+1] = row_head[row_lvl]+1; } /* Interestingly, this super simple timer insert counter works very very * well on distributing the list height uniformly. By means of "very very * well", I mean it beats the randomness of timer->timeout_tick very easily * (actually, the timeout_tick is not random and easy to be attacked). */ random_nr++; tst_nr = random_nr; rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-1], &(timer->row[RT_TIMER_SKIP_LIST_LEVEL-1])); for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK)) rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl], &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl])); else break; /* Shift over the bits we have tested. Works well with 1 bit and 2 * bits. */ tst_nr >>= (RT_TIMER_SKIP_LIST_MASK+1)>>1; } timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED; /* enable interrupt */ rt_hw_interrupt_enable(level); #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* check whether timer thread is ready */ if (timer_thread.stat != RT_THREAD_READY) { /* resume timer thread to check soft timer */ rt_thread_resume(&timer_thread); rt_schedule(); } } #endif return -RT_EOK; }