我正在分析 Pintos 的调度程序(我的意思是 - 由本机实现提供的简单调度程序)。
当一个滴答声(我的意思是计时器引发的滴答声)发生时,它将由以下方式处理:
static void
timer_interrupt (struct intr_frame *args)
{
ticks++;
thread_tick ();
}
args
包含(除其他IP
外)下一条指令中断线程的结构。因此,记住当前线程以让他将来继续工作至关重要。请注意,该处理程序只会增加ticks
和调用thread_tick()
没有args
. 现在,有关eip
(和段寄存器等)的信息丢失了。
这是否意味着提供的调度程序无法继续线程的工作?在这种情况下,它可能是第一个项目的一部分。
我问是因为我不确定我是否误解了某些东西。
我为每个中断处理程序附加了一个“入口点”:
.func intr_entry
intr_entry:
/* Save caller's registers. */
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushal
/* Set up kernel environment. */
cld /* String instructions go upward. */
mov $SEL_KDSEG, %eax /* Initialize segment registers. */
mov %eax, %ds
mov %eax, %es
leal 56(%esp), %ebp /* Set up frame pointer. */
/* Call interrupt handler. */
pushl %esp
.globl intr_handler
call intr_handler
addl $4, %esp
.endfunc
intr_handler
功能:
void intr_handler (struct intr_frame *frame)
{
bool external;
intr_handler_func *handler;
external = frame->vec_no >= 0x20 && frame->vec_no < 0x30;
if (external)
{
ASSERT (intr_get_level () == INTR_OFF);
ASSERT (!intr_context ());
in_external_intr = true;
yield_on_return = false;
}
handler = intr_handlers[frame->vec_no];
if (handler != NULL)
handler (frame);
else if (frame->vec_no == 0x27 || frame->vec_no == 0x2f)
{
// ignore
}
else
unexpected_interrupt (frame);
/* Complete the processing of an external interrupt. */
if (external)
{
ASSERT (intr_get_level () == INTR_OFF);
ASSERT (intr_context ());
in_external_intr = false;
pic_end_of_interrupt (frame->vec_no);
if (yield_on_return)
thread_yield ();
}
}
因此,如您所见intr_handler
,它根本不考虑上下文。基本上,它调用特定的处理程序,如timer_interrupt
(见上文)。timer_interrupt
调用thread_tick
:
void thread_tick (void)
{
struct thread *t = thread_current ();
/* Update statistics. */
if (t == idle_thread)
idle_ticks++;
else
kernel_ticks++;
/* Enforce preemption. */
if (++thread_ticks >= TIME_SLICE)
intr_yield_on_return ();
}
和intr_yield_on_return
:
intr_yield_on_return (void)
{
ASSERT (intr_context ());
yield_on_return = true;
}
intr_yield_on_return
设置标志。intr_handler
有一段代码:
if (yield_on_return)
thread_yield ();
所以它调用thread_yield
:
thread_yield (void)
{
struct thread *cur = thread_current ();
enum intr_level old_level;
ASSERT (!intr_context ());
old_level = intr_disable ();
if (cur != idle_thread)
list_push_back (&ready_list, &cur->elem);
cur->status = THREAD_READY;
schedule ();
intr_set_level (old_level);
}
thread_yield
也不记得IP
当前线程(和其他人)。