Switch task in hand

I am reading the Weapon Architecture Reference Guide and I think I have some theoretical questions.

Well, at first I'm confused, does context switch, do we mean task switch?

Secondly, having experience with the Intel 80386 architecture, I remember that there were task descriptors and some other mechanisms that automatically saved the state of the task, so in hand, how is this done? Is this done, say, "manually", keeping the registers on the stack?

And what ASID (Application Space ID) is related to the previous one that I once asked?


source to share

4 answers

Well, at first I'm confused, does the context switch to task switching?

Yes, task switching is exactly the same as context switcher.

here in hand, how is it done? Is this done, say, "manually", keeping the registers on the stack?

Yes, we store the task context on the stack, typically in the privileged mode stack (IRQ / SVC), copy the context to the task control block, and then restore the context from another task control block that will run. Here's the preliminary code:

    sub lr, lr, 4
    push {lr}
    // push cpu context
    // copy the context to task tcb
    // get tcb of another task which is going to run
    // copy the tcb context back to stack
    // pop cpu context
    pop {pc}


And what ASID (Application Space ID) is related to the previous one that I once asked?

Don't know this



If you have 2 threads with one stack (array of register values), then if you have an ISR that saves the state of the thread and switches to another thread, then this is a context switch. The simplest example is an operating system with two threads (1 producer, 1 consumer), where a switch might look something like this.

 * threadswitch - change thread
 * The thread stack-pointer is supplied as a parameter.
 * The old thread 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_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 );




Here is some code that does exactly what you ask - https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv6-M-ARMv7-M/ARMv6-M-ARMv7-M- PendSV_Handler.cpp . In the exception record, some registers are saved automatically, so you just save the rest, switch the stack pointer, and do the opposite — set aside the "remaining" registers and exit the exception. It gets a little trickier if you also need to store the FPU registers, because they don't need to be saved every time (they are not used if the thread is not doing FPU calculations).



"Context" usually refers to the current state of the CPU; those. the contents of the registers. Each "task" (aka thread) has its own Task Control Block (TCB) structure, which stores relevant information that the OS knows about the task, such as priority, entry point, name, stack size, etc. Typically, the current CPU context is saved on the running task stack when that task is replaced (TCB has a pointer to the task stack). The stack pointer is then stored at a known location (usually in the TCB), and the CPU context is restored with information from the TCB and the next task's stack to start. After switching, the stack pointer points to the stack of the newly started task, and returns to the next command since the last call made by that task. This is a context switch.

I don't know why people point out that the context switch will be in the ISR. A context switch usually occurs during a system call that causes a task in progress to block, such as a sleep call or a semaphore call call, although this can also happen when the system disables the ISR and wakes up a higher priority task or determines that the current task timelist has expired. and another task of equal priority is ready to run. The context switch is just a function called the OS scheduler that gets called from various other system functions, and it doesn't make sense for it to be an ISR, although I'm guessing it could be implemented as a "software" interrupt call, and it might have been in mind.

The point is that context switches are not only due to interruption, but also from other responses. In fact, they are much more common when a system call is executed by a task.



All Articles