CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics Principles of Computers 20 th Lecture Pavel Ježek, Ph.D.
fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver kernel RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 system bus
RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver kernel HAL system bus
RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver word OpenFile(name : string) ReadFile(fd : word;...) WriteFile(fd : word;...) kernel HAL system bus
RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver word OpenFile(name : string) ReadFile(fd : word;...) WriteFile(fd : word;...) kernel HAL VFS: C: system bus
RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver word OpenFile(name : string) ReadFile(fd : word;...) WriteFile(fd : word;...) kernel HAL VFS: MOUSE ALS1 ALS2 C: CON system bus
RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver word OpenFile(name : string) ReadFile(fd : word;...) WriteFile(fd : word;...) kernel HAL VFS: MOUSE ALS1 ALS2 C: CON Ioctl(fd : word;...) system bus
fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF word OpenFile(name : string) ReadFile(fd : word;...) WriteFile(fd : word;...) kernel HAL VFS: MOUSE ALS1 ALS2 C: CON Ioctl(fd : word;...) VFS view by process A A’s file descriptor table (FDT) STDIN FD STDOUT FD word GetStdFd(STDIN or STDOUT) RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 system bus
RS-232 controller HCI: $3F8- $3FF IRQ 4 I 2 C controller HCI (registers, IRQ) VGA HCI: $000A000 - $000AFFF RS-232 controller HCI: $2F8- $2FF IRQ 3 IDE HDC HCI: $1F0- $1F7,$3F6 IRQ 14,DMA keyboard controller HCI: $60-$64 IRQ 1 fdfd Serial APIMouse API I 2 C API Disk API Graphics API Console API Keyb API Operating system API RS-232 controller driver IDE disk controller driver serial mouse driver FileSys API RS-232 controller driver ALS API I 2 C ALS driver Serial API RS-232 to I 2 C bridge driver I 2 C controller driver ALS API I 2 C ALS driver I 2 C API FAT filesystem driver VGA graphics card driver Keyboard controller driver Console window driver Console API Console window driver word OpenFile(name : string) ReadFile(fd : word;...) WriteFile(fd : word;...) kernel HAL VFS: MOUSE ALS1 ALS2 C: CON Ioctl(fd : word;...) VFS view by another process B A’s file descriptor table (FDT) STDIN FD STDOUT FD word GetStdFd(STDIN or STDOUT) system bus
CPU (x86/IA-32)... kernel data... proc table B page tbl A page tbl kernel code stack guard page free B heap B data B code A heap A data A code A PTpage 0B PT 31 0 EIP 31 0 ESP 31 page table base 0 CR3 Non-present Kernel/Supervisor User Read/Only User Read/Write
CPU (x86/IA-32)... kernel data... proc table B page tbl A page tbl kernel code stack guard page free B heap B data B code A heap A data A code A PTpage 0B PT 31 0 EIP 31 0 ESP 31 page table base 0 CR3 Non-present Kernel/Supervisor User Read/Only User Read/Write A’s stack frames B’s stack frames
CPU (x86/IA-32)... kernel data... proc table B page tbl A page tbl kernel code A stack A’s guard page free B stack B’s guard page free B heap B data B code A heap A data A code A PTpage 0B PT 31 0 EIP 31 0 ESP 31 page table base 0 CR3 Non-present Kernel/Supervisor User Read/Only User Read/Write A’s stack frames unused A’s stack B’s stack frames
CPU (x86/IA-32)... kernel data... proc table B page tbl A page tbl kernel code A stack A’s guard page free B stack B’s guard page free B heap B data B code A heap A data A code A PTpage 0B PT 31 0 EIP 31 0 ESP 31 page table base 0 CR3 Non-present Kernel/Supervisor User Read/Only User Read/Write A’s stack frames unused A’s stack B’s stack frames Exec:... procTable[currPID].OldSP := SP; procTable[newPID].StackBottom := AllocateNewStack + PageSize – 1; SP := procTable[newPID].StackBottom;... call Entrypoint... SP := procTable[currPID].OldSP; FreeStackFor(newPID); Exit:... SP := procTable[currPID].StackBottom – entrypoint’s stack frame ret
Process vs. Thread Process state (context): 1)Allocated memory (pages) 2)CPU fault → kernel interrupt handler call procTable[currentPID].faultHandlers[faultID] 3)Open files – e.g. ReadFile(fileDesc,...): read from procTable[currentPID].fdt[fileDesc] 4)Current path – e.g. OpenFile(path,...) if path startsWith ‘/’ or ‘\’ then open file at (path) else open file at (procTable[currentPID].workingDir + path) 5)List of loaded DLLs 6)Page table (state of the address space) 7)PID (Process ID) Thread state (context): 1)Call stack (allocated in context of a process) + SP register! 2)Other CPU registers (IP, FLAGS, general register [if running]) 3)TID (Thread ID)
Thread A: A_entrypoint... call A_main... call funcX... call Exec ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc ExecStartFunc: call DLL entrypoints call B_entrypoint ret Exec CreateProcess IP
Thread A: A_entrypoint... call A_main... call funcX... call Exec ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc ExecStartFunc: call DLL entrypoints call B_entrypoint ret IP Exec CreateProcess
Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc ExecStartFunc: call DLL entrypoints call B_entrypoint ret IP
Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: ret from A_entry ret from A_main ret from funcX ret from Exec A stack maxB stack max SP CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc ExecStartFunc: call DLL entrypoints call B_entrypoint ret IP
Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: ret from A_entry ret from A_main ret from funcX ret from Exec A stack maxB stack max SP CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc ExecStartFunc: call DLL entrypoints call B_entrypoint ret IP
Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY ret from A_entry ret from A_main ret from funcX ret from Exec A stack max ret from B_entry B stack max IP SP ExecStartFunc: call DLL entrypoints call B_entrypoint ret
Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP ret from B_entry ret from funcY B stack max IP
Yield: Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP ret from B_entry ret from funcY ret from Yield B stack max IP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP ret from B_entry ret from funcY ret from Yield B stack max IP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP ret from B_entry ret from funcY ret from Yield B stack max IP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX ret from Exec A stack max SP ret from B_entry ret from funcY ret from Yield B stack max IP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX A stack max SP ret from B_entry ret from funcY ret from Yield B stack max IP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from funcX A stack max ret from B_entry ret from funcY ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY ret from funcZ B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main ret from Yield A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP READY-TO- RUN RUNNING READY-TO-RUN RUNNING READY-TO- RUN RUNNING RUN RTR RUNNING
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary threadTable[currTID].State := READY_TO_RUN; threadTable[nextTID].State := RUNNING; SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP READY-TO- RUN RUNNING READY-TO-RUN RUNNING READY-TO- RUN RUNNING RUN RTR RUNNING
Scheduler
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary threadTable[currTID].State := READY_TO_RUN; threadTable[nextTID].State := RUNNING; SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max IP SP READY-TO- RUN RUNNING READY-TO-RUN RUNNING READY-TO- RUN RUNNING RUN RTR RUNNING CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc context switch
Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary threadTable[currTID].State := READY_TO_RUN; threadTable[nextTID].State := RUNNING; SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max SP RUNNING READY-TO-RUN RUNNING READY-TO- RUN RUNNING RUN RUNNING READY-TO- RUN CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[newTID].OwnerPID := currPID; threadTable[newTID].State := READY_TO_RUN; ret READY-TO-RUN
addr startFunc B stack max Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary threadTable[currTID].State := READY_TO_RUN; threadTable[nextTID].State := RUNNING; SP := threadTable[nextTID].SP; currTID := nextTID; ret Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max SP RUNNING READY-TO-RUN RUNNING READY-TO- RUN RUNNING RUN RUNNING READY-TO- RUN CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack – sizeof(pointer); (threadTable[newTID].SP)^ := startFunc; threadTable[newTID].OwnerPID := currPID; threadTable[newTID].State := READY_TO_RUN; ret READY-TO-RUN threadA.SP
addr startFunc B stack max Thread A: A_entrypoint... call A_main... call funcX... call Exec funcX cont. … ret A_main cont.... call Yield A_main cont.... call Yield Thread B: B_entrypoint... call funcY... call Yield funcY cont.... call funcZ... call Yield ret from A_entry ret from A_main A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max SP RUNNING READY-TO-RUN RUNNING READY-TO- RUN RUNNING RUN RUNNING READY-TO- RUN CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack – sizeof(pointer); (threadTable[newTID].SP)^ := startFunc; threadTable[newTID].OwnerPID := currPID; threadTable[newTID].State := READY_TO_RUN; ret READY-TO-RUN threadA.SP What if startFunc returns?
addr startFunc NEW R-T-R thread CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack – sizeof(pointer); (threadTable[newTID].SP)^ := startFunc; threadTable[newTID].OwnerPID := currPID; threadTable[newTID].State := READY_TO_RUN; ret threadA.SP What if startFunc returns? startFunc running threadA.SP ret from f to sF startFunc called f threadA.SP f returned threadA.SP startFunc returns threadA.SP ?
addr ExitThread addr startFunc NEW R-T-R thread CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack – sizeof(pointer); (threadTable[newTID].SP)^ threadTable[newTID].SP := threadTable[newTID].SP – sizeof(pointer); (threadTable[newTID].SP)^ := startFunc; threadTable[newTID].OwnerPID := currPID; threadTable[newTID].State := READY_TO_RUN; ret threadA.SP What if startFunc returns? addr ExitThread startFunc running threadA.SP addr ExitThread ret from f to sF startFunc called f threadA.SP addr ExitThread f returned threadA.SP startFunc returns threadA.SP
addr ExitThread addr startFunc NEW R-T-R thread CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack – sizeof(pointer); (threadTable[newTID].SP)^ threadTable[newTID].SP := threadTable[newTID].SP – sizeof(pointer); (threadTable[newTID].SP)^ := startFunc; threadTable[newTID].OwnerPID := currPID; threadTable[newTID].State := READY_TO_RUN; ret threadA.SP addr ExitThread startFunc running threadA.SP addr ExitThread ret from f to sF startFunc called f threadA.SP addr ExitThread f returned threadA.SP startFunc returns threadA.SP ExitThread: threadTable[currTID].State := TERMINATED; FreeThreadResourcesAndStack(currTID); jmp Yield;
Multiple Threads Per Process procedure Yield; var nextTID : longword; begin threadTable[currTID].SP := SP; nextTID := GetNextThreadID; if threadTable[currTID].OwnerPID <> threadTable[nextTID].OwnerPID then SwitchProcessContextTo(targetPID: threadTable[nextTID].OwnerPID) currPID := targetPID; CR3 := procTable[currPID].PageTable;... threadTable[currTID].State := READY_TO_RUN; threadTable[nextTID].State := RUNNING; SP := threadTable[nextTID].SP; currTID := nextTID; end;
We’ve Just Implemented Cooperative Multitasking
How to Implement Pascal RTL’s Delay? Active waiting: procedure Delay(delta : longword); begin startTime := currentTime; while currentTime < (startTime + delta) do begin { nothing } end;
How to Implement Pascal RTL’s Delay? Active waiting: procedure Delay(delta : longword); begin startTime := currentTime; while currentTime < (startTime + delta) do begin { nothing } end; Passive waiting: procedure syscall_Sleep(delta : longword); begin endTime := currentTime + delta; threadTable[currTID].State := WAITING; threadTable[currTID].WakeupCondition := WakeupTime(endTime); Yield; end;
Other Conditions Typically Supported by Schedulers procedure syscall_Sleep(delta : longword); begin endTime := currentTime + delta; threadTable[currTID].State := WAITING; threadTable[currTID].WakeupCondition := WakeupTime(endTime); Yield; end; procedure syscall_Join(TID : longword); begin threadTable[currTID].State := WAITING; threadTable[currTID].WakeupCondition := WakeupWhenTerminated(TID); Yield; end;
Doing Something Usefull (Other Threads Run) When Waiting for IRQ procedure syscall_ReadFile(fileDesc : longword,...); begin completed = procTable[currentPID].fdt[fileDesc]^.driver.readProcPtr(...); if not(completed) then begin threadTable[currTID].State := WAITING; threadTable[currTID].WakeupCondition := WakeupOnFileDescritor(fileDesc); Yield; end; IRQ: driver_InterruptHandler: communicate with the controller are further requests necessary? YES: command the controller to execute next request NO: WakeupAllThreads(WakeupOnFileDescritor(currRequest^.fileDesc) IRET
Thread T1 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Thread T1 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Thread T1 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Thread T1 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Thread T1 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem;
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; Context Switch
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; Context Switch next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; Context Switch next prev OtherItem Still a valid doubly-linked list
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Threads T1 and T2 Inserting into A Doubly-Linked List next prev AfterThis next prev NewItem next prev BeforeThis T1: NewItem^.prev := AfterThis; T1: AfterThis^.next^.prev := NewItem; T2: OtherItem^.prev := AfterThis; T2: AfterThis^.next^.prev := OtherItem; T2: OtherItem^.next := AfterThis^.next; T2: AfterThis.next := OtherItem; T1: NewItem^.next := AfterThis^.next; T1: AfterThis.next := NewItem; next prev OtherItem
Is It Thread Safe? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; end;
Is It Thread Safe? In Cooperative Multitasking? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin Yield; { allowed here } NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; no Yield here! NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; Yield; { allowed here } end;
Is It Thread Safe? In Preemptive Multitasking? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; end;
Critical Section Is It Thread Safe? In Preemptive Multitasking? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; end;
Is It Thread Safe? In Preemptive Multitasking? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin asm CLI; NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; asm STI; end;
Critical Section Is It Thread Safe? In Preemptive Multitasking? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; end;
Is It Thread Safe? Using Locks? next prev AfterThis next prev NewItem next prev BeforeThis procedure InsertItem(AfterThis : Node; NewItem : Node) begin Lock(l); NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; Unlock(l); end;
Possible Lock/Unlock Implementation on Uniprocessor System in Kernel procedure InsertItem(AfterThis : Node; NewItem : Node) begin SysCall Lock(l)... in kernel mode: asm CLI; while l.LockOwner <> nil do begin WaitForLock(l); threads[currTID].State := WAITING; threads[currTID].WakeupCondition := LOCK(l); Yield; end; l.LockOwner := currentThread; asm STI; NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; SysCall Unlock(l)... in kernel mode: l.LockOwner := nil; WakeupThreadsWaitingOnLock(l); end;
Possible Lock/Unlock Implementation on Uniprocessor System in Kernel: CLI/STI Is Necessary procedure InsertItem(AfterThis : Node; NewItem : Node) begin SysCall Lock(l)... in kernel mode: asm CLI; while l.LockOwner <> nil do begin WaitForLock(l); threads[currTID].State := WAITING; threads[currTID].WakeupCondition := LOCK(l); Yield; end; l.LockOwner := currentThread; asm STI; NewItem^.prev := AfterThis; AfterThis^.next^.prev := NewItem; NewItem^.next := AfterThis^.next; AfterThis.next := NewItem; SysCall Unlock(l)... in kernel mode: l.LockOwner := nil; WakeupThreadsWaitingOnLock(l); end; Without CLI/STI: RACE CONDITION: A: Owner=nil CTXSWITCH B: Owner=nil, B: Owner:=B CTXSWITCH A: Owner:=A
... kernel data IVT proc table... A’s PT kernel code A stack guard page free...free...free...free 9 8A data 7A data (guard) 6 5A code (guard) 4 3A code 2A code (guard) 1A code 0page 0 Non-present Kernel/Supervisor User Read/Only User Read/Write A’s entrypoint page fault wasted physical memory How to use the otherwise wasted physical memory for another process, if this process A will never access these pages? wasted physical memory
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 logical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] logical address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA)
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 physical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] frame number $00008 = 0000|0000|0000|0000|0010| offset $1F5 = 01|1111| |0000|0000|0000|0010|0001|1111|0101 = $000021F5 physical address logical address = virtual address if paging enabled: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] virtual address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA) IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 free0F free0E free0D free0C free0B free0A free09 A data08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00 physical address space (PA)
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free PT entry: Frame = $00008 Access =08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 logical address = virtual address if paging enabled: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] virtual address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA) physical address space (PA) physical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] frame number $00008 = 0000|0000|0000|0000|0010| offset $1F5 = 01|1111| |0000|0000|0000|0010|0001|1111|0101 = $000021F5 physical address IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 free0F free0E free0D free0C free0B free0A free09 A data08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free PT entry: Frame = $0000F Access =08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 logical address = virtual address if paging enabled: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] virtual address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA) physical address space (PA) physical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] frame number $0000F = 0000|0000|0000|0000|0011| offset $1F5 = 01|1111| |0000|0000|0000|0011|1101|1111|0101 = $00003DF5 physical address IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 free0F free0E free0D free0C free0B free0A free09 A data08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free PT entry: Frame = $0000F Access =08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 logical address = virtual address if paging enabled: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] virtual address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA) physical address space (PA) physical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] frame number $0000F = 0000|0000|0000|0000|0011| offset $1F5 = 01|1111| |0000|0000|0000|0011|1101|1111|0101 = $00003DF5 physical address IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 A data0F free0E free0D free0C free0B free0A free09 free08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 free0F free0E free0D free0C free0B free0A free09 A data08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 free0F free0E free0D free0C free0B free0A free09 A data08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 free0F free0E free0D free0C free0B free0A free09 A data08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code free... free11 free10 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 free00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code free... free11 free10 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 A code00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code free... free11 free10 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 A stack01 A code00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code free... free11 free10 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 A code02 A stack01 A code00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code free... free11 free10 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 A data03 A code02 A stack01 A code00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) IVT proc table... A’s PT kernel code free... free11 free10 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 A stack04 A data03 A code02 A stack01 A code00
kernel data IVT proc table ctrl regs A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) FW ROM free MM I/O free... free11 free10 free0F free0E free0D free0C free0B free0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00
kernel data IVT proc table ctrl regs A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 virtual address space (VA) physical address space (PA) FW ROM free MM I/O free... free11 free10 free0F free0E free0D free0C free0B A stack0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O free VRAM... VRAM11 VRAM10 free0F free0E free0D free0C free0B B’s PT0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06free 05free 04free 03free 02free 01free 00page 0 B’s virtual address space (VA)
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O free VRAM... VRAM11 VRAM10 free0F free0E free0D free0C free0B B’s PT0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06free 05free 04free 03free 02free 01free 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C B code0B B’s PT0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09ALLOC FOR HEAP 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C B code0B B’s PT0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0AALLOC FOR HEAP 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A code05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0AA heap 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0BALLOC FOR HEAP 0AA heap 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0BALLOC FOR HEAP 0AA heap 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 free00 page file (swap)
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10TEMP FRAME $0F 0Ffree 0Efree 0Dfree 0Cfree 0BALLOC FOR HEAP 0AA heap 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 B heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06B heap 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 B 0600 page file (swap)
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0BA heap 0AA heap 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 A heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06in swap: 00 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 B 0600 page file (swap)
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0DALLOC FOR HEAP 2 0CALLOC FOR HEAP 1 0BA heap 0AA heap 09A heap 08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 A heap0F B code0E B data0D B stack0C A heap0B B’s PT0A A stack09 A data08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06in swap: 00 05B data 04B data 03B code (guard) 02B code 01B code (guard) 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 B 0600 page file (swap)
kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code A stack guard page...free 11free 10free 0Ffree 0Efree 0DA heap 0CA heap 0BA heap 0AA heap 09A heap 08in swap: 02 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code (guard) 00page 0 A’s virtual address space (VA) physical address space (PA) FW ROM MM I/O B data VRAM... VRAM11 VRAM10 A heap0F B code0E A heap0D B stack0C A heap0B B’s PT0A A stack09 A heap08 A code07 A stack06 A heap05 A’s PT04 proc table03 kernel code02 kernel code01 IVT00 B’s virtual address space (VA) kernel data IVT proc table ctrl regs B’s PT A’s PT kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07free 06in swap: 00 05B data 04in swap: 01 03B code (guard) 02B code 01B code (guard) 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 A 0802 B 0401 B 0600 page file (swap)
... kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07X.DLL data 06X.DLL code (guard) 05X.DLL code 04Z.DLL data 03Z.DLL code 02A data 01A code 00page 0 A’s virtual address space (VA) physical address space (PA)... free... free11 A stack10 X.DLL data0F Z.DLL data0E Z.DLL code0D A data0C A code0B B stack0A Y.DLL data09 Y.DLL data08 Y.DLL code07 X.DLL data06 X.DLL code05 X.DLL code04 B data03 B code02 B code01 kernel code00 B’s virtual address space (VA)... kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09Y.DLL data 08Y.DLL data 07Y.DLL code 06X.DLL data 05X.DLL code 04X.DLL code 03B data 02B code 01B code 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 free00 page file (swap) DLL Code Sharing
... kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07X.DLL data 06X.DLL code (guard) 05X.DLL code 04Z.DLL data 03Z.DLL code 02A data 01A code 00page 0 A’s virtual address space (VA) physical address space (PA)... free... free11 free10 A stack0F Z.DLL data0E Z.DLL code0D A data0C A code0B B stack0A Y.DLL data09 Y.DLL data08 Y.DLL code07 X.DLL data06 X.DLL code05 X.DLL code04 B data03 B code02 B code01 kernel code00 B’s virtual address space (VA)... kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09Y.DLL data 08Y.DLL data 07Y.DLL code 06X.DLL data 05X.DLL code 04X.DLL code 03B data 02B code 01B code 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 free00 page file (swap) DLL Data Sharing via Copy on Write
... kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07X.DLL data 06X.DLL code (guard) 05X.DLL code 04Z.DLL data 03Z.DLL code 02A data 01A code 00page 0 A’s virtual address space (VA) physical address space (PA)... free... free11 A X.DLL data10 A stack0F Z.DLL data0E Z.DLL code0D A data0C A code0B B stack0A Y.DLL data09 Y.DLL data08 Y.DLL code07 X.DLL data06 X.DLL code05 X.DLL code04 B data03 B code02 B code01 kernel code00 B’s virtual address space (VA)... kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09Y.DLL data 08Y.DLL data 07Y.DLL code 06X.DLL data 05X.DLL code 04X.DLL code 03B data 02B code 01B code 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 free00 page file (swap) DLL Data Sharing via Copy on Write
... kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free 08free 07X.DLL data 06X.DLL code (guard) 05X.DLL code 04Z.DLL data 03Z.DLL code 02A data 01A code 00page 0 A’s virtual address space (VA) physical address space (PA)... free... free11 A X.DLL data10 A stack0F Z.DLL data0E Z.DLL code0D A data0C A code0B B stack0A Y.DLL data09 Y.DLL data08 Y.DLL code07 X.DLL data06 X.DLL code05 X.DLL code04 B data03 B code02 B code01 kernel code00 B’s virtual address space (VA)... kernel code B stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09Y.DLL data 08Y.DLL data 07Y.DLL code 06X.DLL data 05X.DLL code 04X.DLL code 03B data 02B code 01B code 00page 0 free0F free0E free0D free0C free0B free0A free09 free08 free07 free06 free05 free04 free03 free02 free01 free00 page file (swap) DLL Data Sharing via Copy on Write
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free PT entry: Frame = $0000F Access =08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 logical address = virtual address if paging enabled: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] virtual address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA) physical address space (PA) physical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] frame number $0000F = 0000|0000|0000|0000|0011| offset $1F5 = 01|1111| |0000|0000|0000|0011|1101|1111|0101 = $00003DF5 physical address IVT proc table... A’s PT kernel code A stack nothing free... free11 free10 A data0F free0E free0D free0C free0B free0A free09 free08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00
kernel data IVT proc table... A’s PT kernel code A stack guard page free...free 11free 10free 0Ffree 0Efree 0Dfree 0Cfree 0Bfree 0Afree 09free PT entry: Frame = $00F Access =08A data 07A data (guard) 06A data (guard) 05A code (guard) 04A code (guard) 03A code 02A code (guard) 01A code 00page 0 logical address = virtual address if paging enabled: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] virtual address $000021F5 = 0000|0000|0000|0000|0010|0001|1111| page number 0000|0000|0000|0000|0010|00 = $ offset 01|1111|0101 = $1F5 virtual address space (VA) physical address space (PA) physical address: [e.g. for 1 kB = 2 10 B pages & 32-bit address space] frame number $00F = 0000|0000|0011| offset $1F5 = 01|1111| |0000|0011|1101|1111|0101 = $003DF5 physical address IVT proc table... A’s PT kernel code A stack A data0F free0E free0D free0C free0B free0A free09 free08 nothing07 nothing06 nothing05 nothing04 A code03 nothing02 A code01 nothing00 Different sizes of virtual (e.g. 32 bit) and physical (e.g. 24 bit) address spaces are possible! (i7 in x64 mode: 64-bit VA, 48-bit PA)