3

I've been taking a course on operating systems, and in a lecture on context switching, it was mentioned that when a context switch occurs, the OS saves the state of all of the registers to a PCB block, so that the exact state of this process can be resumed when the OS chooses to revisit it.

In assembly, how would someone write the code to save all of this information? As far as I understand, if you want to write any information to memory, you need to have the memory location stored in one of your registers. So, in the process of writing your registers to memory, at least one of your registers has to be overwritten to a location in the PCB block, and the information stored in that register would be lost.

Is there hardware support that makes this task possible?

user129137
  • 71
  • 1
  • 4
  • 2
    The answer to this question strongly depends on the architecture you are programming for. Some architectures like x86 have hardware support, others like SPARC do not. Also, the implementation differs between operating systems, so please narrow down the question at least to a single CPU. – fuz Mar 30 '18 at 20:46
  • Ok, thanks. I was really just curious about this question as I was going through my course, and I wanted to know how something like this could be possible. I'm not developing anything that needs to be able to do this at the moment, and the only architecture I'm familiar with is MIPS, but I haven't worked with it in depth – user129137 Mar 30 '18 at 21:06

2 Answers2

3

Here is an example of how it can be done:
1. Save one register to the stack.
2. Load that register with the address of the PCB.
3. Save all the state in the PCB, including retrieving the register value saved on the stack.

prl
  • 11,716
  • 2
  • 13
  • 31
  • Other tricks that can get used: using a per-CPU *absolute* address, so you can write to it without a pointer in registers. (e.g. on x86-64, `swapgs` to exchange the `gs` segment register with an extra internal register lets you use `mov [gs: 16], rsp` or whatever to save user-space's stack pointer before setting RSP to point to the kernel stack, e.g. with a load from `[gs:0]`). Or the CPU having features to help you, like ARM's register banks that give interrupt handlers a different set of registers from user-space. – Peter Cordes Mar 30 '18 at 22:06
  • Considering the context switch will happen only once (it's not re-entrant, because the next context switch is N [micro]seconds away), you can store one-two registers to some absolute memory, then use those to save full remaining state of CPU somewhere, then load those 1-2 values from the absolute memory and add them to that state to make it complete (if you don't want to clobber user-stack and the interrupt mechanism of your CPU doesn't have separate user/interrupt stack mechanism, like x86_64 does, but on contrary having absolute memory buffer is possible). – Ped7g Mar 31 '18 at 09:18
  • 1
    @Ped7g: What if a network-card or sound-card interrupt comes in during this, triggering wake-up of a real-time process that has priority over the one you were switching to? With a pre-emptible kernel (like modern Linux) it's non-obvious that you couldn't end up treating the state in the middle of a save as an old context that you want to resume later. You may need to run this part of state-saving with interrupts disabled so you can safely use an absolute memory location. (Linux uses the bottom of the per-thread kernel stack for user-space state, but IDK for kernel-preemption) – Peter Cordes Mar 31 '18 at 18:40
  • (BTW, this absolute location trick is used in modern OSes in the save-everything code which happens on entry into the kernel from user-space. `__switch_to` inside the kernel looks like a function (called from `sched()`), so the caller already expects it to clobber some regs, and thus it has some scratch regs to play with. **[How does schedule()+switch_to() functions from linux kernel actually work?](https://stackoverflow.com/questions/6525905/how-does-scheduleswitch-to-functions-from-linux-kernel-actually-work)**. https://github.com/torvalds/linux/blob/master/arch/x86/entry/entry_64.S#L333 – Peter Cordes Mar 31 '18 at 18:49
-1

In general, a processor defines a Process Context Block (PCB). This is a data structure in which the processor stores into and loads from the registers. For the most part the operating system does not really need to know the internal structure of the PCB, only the size.

Processors generally have a Load Process Context and Save Process Context instruction. For simplicity, assume you have process context blocks with the labels PROCESS_1 and PROCESS_2 where the former is the current running process, to switch processes you do something like:

 SVPCTX  PROCESS_1
 LDPCTX  PROCESS_2 ; As soon as this instruction execute the context switch is complete.

This can be more complex on some systems that have multiple register sets (say "Hi" Intel) but what I have described is how it generally works on most processors.

user3344003
  • 20,574
  • 3
  • 26
  • 62
  • So you're suggesting that you can use static storage for PCBs? That works if you have a few pre-defined contexts, and the new / old context are assemble-time constants. That doesn't scale to an arbitrary number of processes. – Peter Cordes Mar 30 '18 at 22:54
  • No I am not. Note the "For simplicity" qualifier. In reality, there were be some register based addressing. To dynamic data structures. – user3344003 Mar 30 '18 at 23:52
  • Then how do you save that register before clobbering it with a pointer to the PCB? The answer is a combination of the two-step saving all user-space context in a known spot on entry to the kernel (system call or interrupt entry point) like @prl's answer, and then making the context-switch a function-call that doesn't have to save/restore all the registers. – Peter Cordes Mar 30 '18 at 23:54
  • You don't save the register pointing to the PCB. As soon as you do a load process context you are in the new process and don't care. – user3344003 Mar 30 '18 at 23:56
  • But you need to eventually be able to come back to the saved context, so it has to contain the entire user-space architectural state. When you first enter the kernel, with all registers holding user-space state you need to avoid corrupting, it's non-obvious how / where you can save anything. A static location needs to be used carefully so it's not clobbered. I think that's the essence of what the OP is asking. – Peter Cordes Mar 30 '18 at 23:58
  • That depends upon the system. As a simple example, the VAX (whose mnemonic I used) stores the PC and the Processor Status from the stack rather into the PCA rather than taking it directly from the registers, – user3344003 Mar 31 '18 at 00:05