我正在分析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
(和其他人)当前的帖子。