之前对线程关注较少,只是简单用了api,现在看看具体的实现
void thread_block(void)
{
#if THREAD_CHECKS
ASSERT(current_thread->magic == THREAD_MAGIC);
ASSERT(current_thread->state == THREAD_BLOCKED);
#endif
enter_critical_section();
/* we are blocking on something. the blocking code should have already stuck us on a queue */
thread_resched();
exit_critical_section();
}
看看
/**
* @brief Cause another thread to be executed.
*
* Internal reschedule routine. The current thread needs to already be in whatever
* state and queues it needs to be in. This routine simply picks the next thread and
* switches to it.
*
* This is probably not the function you're looking for. See
* thread_yield() instead.
*/
void thread_resched(void)
{
thread_t *oldthread;
thread_t *newthread;
// dprintf("thread_resched: current %p: ", current_thread);
// dump_thread(current_thread);
#if THREAD_CHECKS
ASSERT(in_critical_section());
#endif
#if THREAD_STATS
thread_stats.reschedules++;
#endif
oldthread = current_thread; //把当前thread赋值给old
// at the moment, can't deal with more than 32 priority levels
ASSERT(NUM_PRIORITIES <= 32);
// should at least find the idle thread
#if THREAD_CHECKS
ASSERT(run_queue_bitmap != 0);
#endif
int next_queue = HIGHEST_PRIORITY - __builtin_clz(run_queue_bitmap) - (32 - NUM_PRIORITIES);
//dprintf(SPEW, "bitmap 0x%x, next %d\n", run_queue_bitmap, next_queue);
newthread = list_remove_head_type(&run_queue[next_queue], thread_t, queue_node); //找到下一个新的thread
#if THREAD_CHECKS
ASSERT(newthread);
#endif
if (list_is_empty(&run_queue[next_queue]))
run_queue_bitmap &= ~(1<<next_queue);
#if 0
// XXX make this more efficient
newthread = NULL;
for (i=HIGHEST_PRIORITY; i >= LOWEST_PRIORITY; i--) {
newthread = list_remove_head_type(&run_queue[i], thread_t, queue_node);
if (newthread)
break;
}
#endif
// dprintf("newthread: ");
// dump_thread(newthread);
newthread->state = THREAD_RUNNING; //设置newthread的状态为run
if (newthread == oldthread)
return;
/* set up quantum for the new thread if it was consumed */
if (newthread->remaining_quantum <= 0) {
newthread->remaining_quantum = 5; // XXX make this smarter
}
#if THREAD_STATS
thread_stats.context_switches++;
if (oldthread == idle_thread) { //<span style="color: rgb(17, 17, 17); font-size: 13px; line-height: 21.0599994659424px; white-space: pre-wrap;">idle 进程优先级为MAX_PRIO,即最低优先级。早先版本中,idle是参与调度的,所以将其优先级设为最低,当没有其他进程可以运行时,才会调度执行 idle。</span>
bigtime_t now = current_time_hires();
thread_stats.idle_time += now - thread_stats.last_idle_timestamp;
}
if (newthread == idle_thread) {
thread_stats.last_idle_timestamp = current_time_hires();
}
#endif
#if THREAD_CHECKS
ASSERT(critical_section_count > 0);
ASSERT(newthread->saved_critical_section_count > 0);
#endif
#if PLATFORM_HAS_DYNAMIC_TIMER
/* if we're switching from idle to a real thread, set up a periodic
* timer to run our preemption tick.
*/
if (oldthread == idle_thread) {
timer_set_periodic(&preempt_timer, 10, (timer_callback)thread_timer_tick, NULL);
} else if (newthread == idle_thread) {
timer_cancel(&preempt_timer);
}
#endif
/* do the switch */
oldthread->saved_critical_section_count = critical_section_count;
current_thread = newthread;
critical_section_count = newthread->saved_critical_section_count;
arch_context_switch(oldthread, newthread);
}
其实还应该关系old thread干啥去了,详情需要参考http://blog.csdn.net/xiaojsj111/article/details/14648233
大概就是这样