multithreadingkernelexecutioncontext-switch

Core execution flow in the point of thread context switch and CPU mode switch


If

I want to know simplified core execution flow in the point of thread context switch and CPU mode switch per time slice.

My understanding is as follows. Please correct me if I'm wrong.

In case of the thread is kernel managed user mode thread not involving interrupt, or anything that requires kernel mode,

  1. The thread context switch occurs.
  2. The core executing thread switches to kernel mode because context switch can only occur in kernel mode according to here, here and here unless the thread is user managed thread.
  3. The core executing thread switches to user mode.
  4. The core executes sequence of instructions located in user space.
  5. Time slice expires.
  6. Repeat 1.

Closest related diagram I could find is below.

Even a little clue to answer will be sincerely appreciated.


Solution

  • You said it yourself:

    context switch can only occur in kernel mode

    So the CPU must enter kernel mode before there can be a context switch. That can happen in either one of two ways in most operating systems:

    1. The user-mode code makes a system call, or
    2. An interrupt occurs.

    If the thread enters kernel mode by making a system call, then there could be a context switch if the syscall causes the thread to no longer be runnable (e.g., a sleep() call), or there could be a context switch if the syscall causes some higher-priority thread to become runnable. (e.g., the syscall releases a mutex that the higher priority thread was awaiting.)

    If the thread enters kernel mode because of an interrupt, then there could be a context switch because the interrupt handler made some higher-priority thread runnable (e.g., if the other thread was awaiting data from the disk), or there could be a context switch because it was a timer interrupt, and the current thread's time slice has expired.


    The mechanism of context switching may be different on different hardware platforms. Here's how it could happen on some hypothetical CPU:

    1. The current thread (threadA) enters sheduler code which chooses some other thread (threadB) as the next to run on the current CPU.
    2. It calls some switchContext(threadB) function.
    3. The switchContext function copies values from the stack pointer register, and from other live registers into the current thread (threadA)'s saved context area.*
    4. It then sets the "current thread" pointer to point to threadB's saved context area, and it restores threadB's context by copying all the same things in reverse.**
    5. Finally, the switchContext function returns... IN threadB,... at exactly the place where threadB last called it.

    Eventually, threadB returns from the interrupt or system call to application code running in user-mode.


    * The author of switchContext may have to be careful, may have to do some tricky things, in order to save the entire context without trashing it. E.g., it had better not use any register that needs saving before it has actually saved it somewhere.

    ** The trickiest part is when restoring the stack pointer register. As soon as that happens, "the" stack suddenly is threadB's stack instead of threadA's stack.