3

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

4

0 回答 0