Arm中的任务切换

Arm中的任务切换,arm,context-switch,Arm,Context Switch,我正在阅读Arm架构参考手册,我想我有一些理论问题 首先我很困惑,上下文转换是否意味着任务转换 其次,通过对Intel 80386体系结构的体验,我记得有任务描述符和一些其他机制可以自动保存任务状态,在arm中,它是如何完成的?它是通过在堆栈中保存寄存器来完成的,比如说“手动”完成的吗 ASID(应用程序空间ID)与我问过的前一个链接 如果有两个线程,每个线程有一个堆栈(寄存器值数组),那么如果有一个ISR保存线程的状态并切换到另一个线程,那么这就是上下文切换。最简单的例子是一个具有2个线程(1

我正在阅读Arm架构参考手册,我想我有一些理论问题

首先我很困惑,上下文转换是否意味着任务转换

其次,通过对Intel 80386体系结构的体验,我记得有任务描述符和一些其他机制可以自动保存任务状态,在arm中,它是如何完成的?它是通过在堆栈中保存寄存器来完成的,比如说“手动”完成的吗


ASID(应用程序空间ID)与我问过的前一个链接

如果有两个线程,每个线程有一个堆栈(寄存器值数组),那么如果有一个ISR保存线程的状态并切换到另一个线程,那么这就是上下文切换。最简单的例子是一个具有2个线程(1个生产者,1个消费者)的操作系统,其中的开关可以类似于此处的代码

/*
 * threadswitch - change thread
 * 
 * The thread stack-pointer is supplied as a parameter.
 * The old thread's stack-pointer value is saved to the array
 * os_thread_info_array, and a new thread is selected from the array.
 * The stack pointer of the new thread is returned.
 */
unsigned int os_internal_threadswitch( unsigned int old_sp )
{
  unsigned int new_sp;

  os_number_of_thread_switches += 1; /* Increase thread-switch counter. */

  /* Print line 1 of an informational message. */
  printf( "\nPerforming thread-switch number %d. The system has been running for %d ticks.\n",
          os_number_of_thread_switches,
          os_get_internal_globaltime() );

  /* Save the stack pointer of the old thread. */
  os_thread_info_array[ os_currently_running_thread ].thread_sp = old_sp;

  /* Print part 1 of a message saying which threads are involved this time. */
  printf( "Switching from thread-ID %d ",
          os_thread_info_array[ os_currently_running_thread ].thread_id );

  /* Perform the scheduling decision (round-robin). */
  os_currently_running_thread += 1;
  if( os_currently_running_thread >= os_current_thread_count )
  {
    os_currently_running_thread = 0;
  }

  /* Print part 2 of the informational message. */
  printf( "to thread-ID %d.\n",
          os_thread_info_array[ os_currently_running_thread ].thread_id );

  /* Get the stack pointer of the new thread. */
  new_sp = os_thread_info_array[ os_currently_running_thread ].thread_sp;

  /* Return. */
  return( new_sp );
}

下面是一个代码,它完全符合您的要求-。在异常条目中,一些寄存器会自动保存,所以您只需保存其余的寄存器,切换堆栈指针并执行相反的操作—取消“剩余”寄存器的堆栈并退出异常。如果您还需要保存FPU寄存器,这会变得有点困难,因为不需要每次都保存这些寄存器(如果线程不进行任何FPU计算,它们将不被使用)

首先我很困惑,上下文转换是否意味着任务转换

是的,任务切换与上下文切换完全相同

这是怎么做的?它是通过在堆栈中保存寄存器来完成的,比如说“手动”完成的吗

是的,我们将任务上下文保存在堆栈上,通常保存在特权模式(IRQ/SVC)堆栈上,将上下文复制到任务控制块中,然后从将要运行的另一个任务控制块恢复上下文。以下是一个PRESSDO代码:

irq_handler:
    sub lr, lr, 4
    push {lr}
    // push cpu context
    // copy the context to task's tcb
    // get tcb of another task which is going to run
    // copy the tcb context back to stack
    // pop cpu context
    pop {pc}
ASID(应用程序空间ID)与我问过的前一个链接

“上下文”通常指CPU的当前状态;i、 e.登记册的内容。每个“任务”(也称为线程)都有自己的任务控制块结构(TCB),它存储操作系统知道的关于任务的相关信息,如优先级、入口点、名称、堆栈大小等。通常,只要任务被调出,当前CPU上下文就会保存在正在运行的任务的堆栈上(TCB有一个指向任务堆栈的指针)。然后将堆栈指针保存到已知位置(通常在TCB中),CPU上下文将使用来自TCB的信息和要运行的下一个任务的堆栈进行还原。切换后,堆栈指针指向新运行任务的堆栈,并返回到该任务上次调用后的下一条指令。这是上下文切换

我不知道为什么人们会指出上下文切换将位于ISR中。上下文切换通常发生在导致正在运行的任务阻塞的系统调用期间,例如睡眠调用或信号量get调用,但也可能发生在系统勾选ISR运行并唤醒更高优先级的任务时,或者确定当前task的时间片已过期,另一个同等优先级的任务已准备好运行。上下文切换只是操作系统调度程序调用的一个函数,它是从各种其他系统函数调用的,它作为ISR没有意义,尽管我认为它可以作为“软件”实现打断电话,也许这就是他们的想法


关键是,上下文切换不仅仅是由于中断而发生的,这是我从其他响应中得到的印象。事实上,当任务进行系统调用时,它们发生的频率要高得多。

不知道您读到的上下文切换的确切内容,但这可能就是它们所谈论的内容。一般来说,从硬件透视图您需要保存状态以切换到另一个上下文。基本上,保存一个上下文的寄存器,并恢复先前上下文的寄存器/状态并继续运行。从更高级别的程序员角度来看,可以将其称为上下文、线程、任务,无论您想要什么…上下文切换指的是任务切换?这些是十不严格地使用。然而,上下文切换通常意味着寄存器。而任务切换意味着更新MMU表。ASID和任务描述符与MMU相关。然而,ARM/x86使用不同的缓存,MMU/缓存交互很重要。Google VIVT和PIPT。很好的描述。但是,为什么要将上下文保存在上特权模式(IRQ/SVC)堆栈?这对我来说没有意义。它应该保存在线程的堆栈上,而不是特权堆栈上。因为每个线程都有自己的堆栈,但只有一个特权模式堆栈。或者我有什么误解?