Week 03a CS6640 01/20 2026 https://naizhengtan.github.io/26spring/ □ 0. Admin □ 1. Recap: threading □ 2. egos assembly I □ 3. Context switches in user-space --- 0. Admin: - Q: how many of you have submitted your lab1? - Q: how's your lab1? - Lab2 will release soon 1. Recap: threading A) Review: processes and kernel-managed threads? (We refer to that as "kernel-level threading.") [draw process and threads] Two views of processes: OS kernel and apps from kernel, PCB (process control block): - its view of memory (for x86, %cr3) - its view of CPU (registers) - (file descriptor table) - (other metadata) [show grass/process.h] TCB (thread control block): - thread's view of CPU (registers) [draw a memory layout of two threads] Recall basic segments of a memory layout: stack, code, heap, data Q: what C program "components" do the four carry? -- stack: local variables -- text: code -- heap: malloc'ed memory -- data: global variables Q: are all four absolutely necessary? Can we get rid of some? What's the minimum set of segments that a program can run? "a program can run with only stack and code sections." without having to have heap, data, and other things. -- basically same as a process, except two threads in the same process have the same address space (in RISC-V, that means having the same satp register) B) thread preemption -- Q: What is preemption? the ability for OS or threading package to (a) forcibly interrupt a running thread and (b) switches execution to another thread without the thread's cooperation -- kernel threads are always preemptive -- How about user-level threading? C) user-level threads - We can also have *user*-level threading, in which the kernel is completely ignorant of the existence of threading. [draw picture] T1 T2 T3 thr package OS H/W -- in this case, the threading package is the layer of software that maintains the array of TCBs (thread control blocks) Responsibilities of threading package: 1. manage threads (TCBs) 2. create threads (allocating stacks) Q: does threading package need to allocate heap for new threads? [A: No, threads share heap.] Q: does threading package need to allocate code sections for new threads? [A: No, threads share code.] 3. scheduling 4. context switch! (in user-space) -- user-level threading can be non-preemptive (cooperative, your Lab2) or preemptive (your final project?). We'll look at both. --but first, let's take a look at context switches in user-space. --preview: context swtiches are cases when... ...threading package saves the execution state of a running thread and... ...restores the state of another thread to transfer control of the CPU. --Q: Why context switches? A: enabling multiplexing of the CPU across threads or processes. 2. egos assembly I Q: so...what is the "context" in context switches? - introduce registers [see handout_asm] pc: program counter (not part of the handout) sp: stack pointer ra: return address a0: the first argument a0: return values - Overview: Calling Conventions -- [draw calling diagram of foo() and bar()] -- when a function foo() calls another function bar() -- how bar() locates its input arguments and where to put the outputs -- how foo() determines which registers remain unchanged after bar() returns -- caller-saved and callee-saved registers -- [see the calling convention doc on Reference page] - five assembly instructions -- [see instructions list doc on Reference page] - go through helloworld example [see asm handout panel 3 and 4] -- prologue and epilogue Q: what will happen when 'ret' from main()? [show apps/app.s] Q: Why print_hello() asm says "80200534 ", rather than ""? A: egos does not use libc's standard printf implementation; in fact, you have implemented part of the printf (see library/libc/print.c) 3. Context switches in user-space A) context in processes and threads Let's again start from process. - What is execution "context" for a process? Informally, the context represents the state of a process that, if altered unexpectedly, would disrupt its execution. Q: which is process's context? A. %pc B. %sp C. stack D. heap E. other processes' memory [Anser: A, B, C, D] A canonical process "context" really is about two things: - switching the view of memory (address space; x86's %cr3) - switching the registers (including stack pointer, meaning switching the stack) Now, consider threads: Q: which is thread's context? A. %pc B. %sp C. stack D. heap E. other processes' memory [Anser: A, B] The memory isn't relevant for user-level threading. B) context switch is switching between two contexts How context switch works in your lab2? [see handout_ctx] - go through a ctx_switch (i) go through high-level description [draw two stacks] (ii) go through the code Q: what is "a0"? what is "0(a0)"? A: first argument (see calling convention); dereference the first argument (which is "void** old_sp") Q: when ctx_switch() finishes, it runs "ret"; where it returns to? A: next of "ctx_switch()". Q: why the code only saves callee-saved's registers? A: caller-saved registers are saved by caller, which is... ...whoever called ctx_switch(). - Now, ctx_switch() assumes the other stack has "context" (the registers). How to create such a "context" on stack? Answer is using "ctx_start". [See handout panel 3]