Download presentation
Presentation is loading. Please wait.
1
Principles of Computers 21st Lecture
Pavel Ježek, Ph.D.
2
Back To Simplified View: Concept of an HBA (Host Bus Adapter)
Code executed by CPU: MOV EAX, h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space Code executed by CPU: MOV AL, 05h ; load 8-bit constant MOV [ h], AL ; 8-bit store addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: addr 1 1 B register Y MWr 2 B register X reg Y system bus $ reg X $FFFFFFFF = 232-1 4 GB device B $ addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $ 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $ = 0 1 B register 1 B register 1 B register
3
Graphics Card HCI
4
8-bit Sound Card HCI DAC Address decode Playback logic Data W/O reg
sound buffer (100kB – MB) RWAddr reg ... $F $F DD $F $F $F $F DAC PlayAdr reg auto increment auto increment Loudspeaker image (CC Attribution) authored by Sallee Design,
5
16-bit Sound Card HCI (Byte Ordering as Part of HCI)
Address decode Playback logic Data W/O reg MSB LSB sound buffer (100kB – MB) RWAddr reg ... $F DD $F $F $F $F $F DAC PlayAdr reg auto increment on MSB write (LSB and MSB must be written at once during a single 16-bit write [if on 16-bit system bus] or LSB must be written first and MSB second if on 8-bit system bus) auto increment Loudspeaker image (CC Attribution) authored by Sallee Design,
6
16-bit Sound Card HCI DAC Address decode Playback logic Data W/O reg
MSB LSB sound buffer (100kB – MB) RWAddr R/W reg ... $F DD $F $F AA $F $F $F DAC PlayAdr reg auto increment auto increment Loudspeaker image (CC Attribution) authored by Sallee Design,
7
16-bit Sound Card HCI DAC Address decode Playback logic Data W/O reg
MSB LSB sound buffer (100kB – MB) RWAddr R/W reg ... $F DD $F $F AA $F CF $F $F DAC PlayAdr reg auto increment Config R/W reg ▪sample rate ▪sample size ▪mono/stereo auto increment Loudspeaker image (CC Attribution) authored by Sallee Design,
8
16-bit Sound Card HCI DAC Address decode Playback logic Data R/W reg
MSB LSB sound buffer (100kB – MB) RWAddr R/W reg ... $F DD $F $F AA $F CF $F CT $F DAC PlayAdr reg auto increment Config R/W reg ▪sample rate ▪sample size ▪mono/stereo auto increment Control W/O reg ▪play/stop ▪record/stop Loudspeaker image (CC Attribution) authored by Sallee Design,
9
16-bit Sound Card HCI DAC Address decode Playback logic Data R/W reg
MSB LSB sound buffer (100kB – MB) RWAddr R/W reg ... $F DD $F $F AA $F CF $F CT $F ST DAC PlayAdr reg auto increment Config R/W reg ▪sample rate ▪sample size ▪mono/stereo auto increment Control W/O reg ▪play/stop ▪record/stop Status R/O reg ▪play position ▪playing? ▪recording? Loudspeaker image (CC Attribution) authored by Sallee Design, Base address: $F
10
PIO (Programmed I/O) – Reading 1 Byte From Controller
6502: LDA ctrl_data_reg_address STA buffer_address
11
PIO (Programmed I/O) 6502: 1 tx = read/fetch load instruction opcode
LDA ctrl_data_reg_address STA buffer_address 1 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 1 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 4 tx
12
PIO (Programmed I/O) 6502: 1 tx = read/fetch load instruction opcode
LDA ctrl_data_reg_address STA buffer_address 1 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 1 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 4 tx 6502: LDA addr = 3 byte instruction STA addr = 3 byte instruction 3 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 3 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 8 tx
13
PIO (Programmed I/O) 6502: 1 tx = read/fetch load instruction opcode
LDA ctrl_data_reg_address STA buffer_address 1 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 1 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 4 tx 6502: LDA addr = 3 byte instruction STA addr = 3 byte instruction 3 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 3 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 8 tx e.g. system bus: 1 byte/tx 2 cycles/tx 1 MHZ cycles = 0,5 MB/second = x B/s PIO transfer = (x / 8) B/s = 62,5 kB/s
14
PIO (Programmed I/O) Solution: DMA 6502:
LDA ctrl_data_reg_address STA buffer_address 1 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 1 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 4 tx 6502: LDA addr = 3 byte instruction STA addr = 3 byte instruction 3 tx = read/fetch load instruction opcode 1 tx = read data from controller’s data register 3 tx = read/fetch store instruction opcode 1 tx = write data from A to buffer in memory = 8 tx e.g. system bus: 1 byte/tx 2 cycles/tx 1 MHZ cycles = 0,5 MB/second = x B/s PIO transfer = (x / 8) B/s = 62,5 kB/s Solution: DMA
15
CPU Is Master / Devices Are Slaves
Code executed by CPU: MOV EAX, h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space Code executed by CPU: MOV AL, 05h ; load 8-bit constant MOV [ h], AL ; 8-bit store master addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 slave memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: addr 1 1 B register Y MWr 2 B register X slave reg Y system bus $ reg X $FFFFFFFF = 232-1 4 GB device B $ addr 8 slave 1 B register device C = bus 2 controller (HBA) bus 2 $ 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 slave 1 B register addr 13 addr 1 device D device E $ = 0 1 B register 1 B register 1 B register
16
Programming Target Address for DMA Write
CPU 32-bit physical address space master memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: 1 B register Y MWr 2 B register X reg Y system bus slave $ reg X $FFFFFFFF = 232-1 4 GB device B $ 1 B register device C = bus 2 controller (HBA) bus 2 $ 512 MB $5FFFFFFF 1 GB $3FFFFFFF = 230-1 1 B register device D device E $ = 0 1 B register 1 B register 1 B register
17
DMA Write CPU slave master memory controller (refresh) 1 GB DRAM
32-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr slave memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: MWr 1 B register Y master 2 B register X reg Y system bus $ reg X $FFFFFFFF = 232-1 4 GB device B $ 1 B register device C = bus 2 controller (HBA) bus 2 $ 512 MB $5FFFFFFF 1 GB $3FFFFFFF = 230-1 1 B register device D device E $ = 0 1 B register 1 B register 1 B register
18
16-bit Sound Card HCI DAC Address decode Playback logic Data R/W reg
MSB LSB sound buffer (100kB – MB) RWAddr R/W reg ... $F DD $F $F AA $F CF $F CT $F ST DAC PlayAdr reg auto increment Config R/W reg ▪sample rate ▪sample size ▪mono/stereo auto increment Control W/O reg ▪play/stop ▪record/stop Status R/O reg ▪play position ▪playing? ▪recording? Loudspeaker image (CC Attribution) authored by Sallee Design, Base address: $F
19
16-bit Sound Card HCI with DMA Bus Master
Address decode Playback logic DMA Addr R/W reg 32-bit ... $F000010A A3 $F A2 $F A1 $F A0 $F L3 $F L2 $F L1 $F L0 $F CF $F CT $F ST sound buffer (100kB – MB) auto increment DMA Length R/W reg 32-bit DAC PlayAdr reg DMA BufferAddr reg Config R/W reg ▪sample rate ▪sample size ▪mono/stereo auto increment auto increment Control W/O reg ▪play/stop ▪record/stop Status R/O reg ▪play position ▪playing? ▪recording? Loudspeaker image (CC Attribution) authored by Sallee Design, Base address: $F
20
DMA: Do Not Forget: Logical vs. Physical Address Space
CPU arch. CPU name Data width Logical address width Current instruction register(s) Physical address width 8-bit 6502 MOS 6502 8-bit data 16-bit PC (64 kB) x86-16 x86 Intel 8088 bit 20-bit (1 MB) Intel 8086 16-bit data logical address (16 bit & 16 bit): Segment:Offset physical address (20 bit): (Segment * 16) + Offset logical address: $AAAA:$0000 physical address: $AAAA * 16 = $AAAA shl 4 = $AAAA0 + $0000 = $AAAA0
21
Where To Get Initial Code on Von Neumann Architeture?
CPU 32-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: 1 B register Y 2 B register X reg Y system bus $ reg X $FFFFFFFF = 232-1 4 GB device B $ 1 B register device C = bus 2 controller (HBA) bus 2 $ 512 MB $5FFFFFFF 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $ = 0 1 B register 1 B register 1 B register
22
System Bus – Firmware ROM
CPU comm. protocol: 20-bit address space 1 MB ROM module 32-bit physical address space memory bus memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: 1 B register Y 2 B register X reg Y system bus $ reg X $FFFFFFFF = 232-1 4 GB FW ROM device B $ 1 B register device C = bus 2 controller (HBA) bus 2 $ 512 MB $5FFFFFFF 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $ = 0 1 B register 1 B register 1 B register
23
PURPLE = computer firmware code executed by CPU
firmware test and configures HW firmware tries to locate SW to run
24
PURPLE = computer firmware code executed by CPU
firmware test and configures HW firmware checks and calls option ROMs
25
PURPLE = computer firmware code executed by CPU
firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM
26
Example of Firmware ABI via Software Interrupts
BIOS API functions/procedures Interrupt vector (arguments passed in registers) Disk access – e.g. read sector $13 Screen output – e.g. print text to screen $10 Keyboard input – e.g. read last key pressed $16 Get total amount of RAM installed $12 Get memory map $15
27
PURPLE = computer firmware code executed by CPU
GREEN = boot loader code executed by CPU firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with application code/data loaded to RAM call application entrypoint
28
PURPLE = computer firmware code executed by CPU
GREEN = boot loader code executed by CPU firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint
29
PURPLE = computer firmware code executed by CPU
GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLUE = user program code executed by CPU firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint kernel init call Exec(‘Prog.exe’) load Prog.exe call Prog.exe entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE ...
31
PURPLE = computer firmware code executed by CPU
GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER
32
PURPLE = computer firmware code executed by CPU
GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE
33
Selected Faults/Traps/Exceptions of x86 ISA
CPU Exception Interrupt vector (all push IP of faulting instruction) Invalid opcode 6 Divide by zero (DIV0) Alignment check 17 ($11)
34
Selected Faults/Traps/Exceptions of x86 ISA
CPU Exception Interrupt vector (all push IP of faulting instruction) Invalid opcode 6 Divide by zero (DIV0) Alignment check 17 ($11) General Protection Fault 13 ($0D)
35
CPU starts in supervisor mode
PURPLE = computer firmware code executed by CPU GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE
36
PURPLE = computer firmware code executed by CPU
GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE Kernel sets super := 0, CPU gets to user mode
37
Cannot disable HW interrupts (IRQs)
PURPLE = computer firmware code executed by CPU GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE Kernel sets super := 0, CPU gets to user mode Cannot modify IVT Cannot disable HW interrupts (IRQs) Kernel code runs in user mode :(
38
INT n instruction is executed by the CPU as an atomic sequence of:
PURPLE = computer firmware code executed by CPU GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint INT n instruction is executed by the CPU as an atomic sequence of: PUSHF ← push flags register to stack CLI ← disable HW interrupts CALL [IVT[n]] ← call actual interrupt handler (works in this way for SW interrupts, CPU faults, and HW interrupts) kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE Kernel sets super := 0, CPU gets to user mode Cannot modify IVT Cannot disable HW interrupts (IRQs) Kernel code runs in user mode :(
39
INT n instruction is executed by the CPU as an atomic sequence of:
PURPLE = computer firmware code executed by CPU GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint INT n instruction is executed by the CPU as an atomic sequence of: PUSHF ← push flags register to stack flags.supervisor := 1 ← call actual interrupt handler CLI ← disable HW interrupts CALL [IVT[n]] ← call actual interrupt handler (works in this way for SW interrupts, CPU faults, and HW interrupts) kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE Kernel sets super := 0, CPU gets to user mode Syscall switches CPU to supervisor mode
40
INT n instruction is executed by the CPU as an atomic sequence of:
PURPLE = computer firmware code executed by CPU GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint INT n instruction is executed by the CPU as an atomic sequence of: PUSHF ← push flags register to stack flags.supervisor := 1 ← call actual interrupt handler CLI ← disable HW interrupts CALL [IVT[n]] ← call actual interrupt handler (works in this way for SW interrupts, CPU faults, and HW interrupts) kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE Kernel sets super := 0, CPU gets to user mode Syscall switches CPU to supervisor mode IRET from syscall restores flags, so super := 0, so CPU switches back to user mode
41
INT n instruction is executed by the CPU as an atomic sequence of:
PURPLE = computer firmware code executed by CPU GREEN = boot loader code executed by CPU RED = kernel code executed by CPU BLACK = shell code executed by CPU BLUE = user program code executed by CPU CPU starts in supervisor mode firmware test and configures HW firmware checks and calls option ROMs firmware tries to find bootable drive: load boot sector to RAM jump/call to boot sector entrypoint in RAM boot loader running repeat call ReadSector firmware API firmware communicates with drive’s controller firmware stores received sectors data into RAM until all sectors with kernel code/data loaded to RAM call kernel entrypoint INT n instruction is executed by the CPU as an atomic sequence of: PUSHF ← push flags register to stack flags.supervisor := 1 ← call actual interrupt handler CLI ← disable HW interrupts CALL [IVT[n]] ← call actual interrupt handler (works in this way for SW interrupts, CPU faults, and HW interrupts) kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat call ReadKey kernel API kernel communicates with keyboard controller key := result of ReadKey call PrintCharacter kernel API kernel communicates with graphics card until key <> ENTER call Exec(‘Prog.EXE’) load Prog.EXE call Prog.EXE entrypoint ... Prog.EXE’s RTL initialization code ... main program of Prog.EXE Kernel sets super := 0, CPU gets to user mode Syscall switches CPU to supervisor mode IRET from syscall restores flags, so super := 0, so CPU switches back to user mode Syscall switches CPU to supervisor mode IRET from syscall restores flags, so super := 0, so CPU switches back to user mode
42
Selected Faults/Traps/Exceptions of x86 ISA
CPU Exception Interrupt vector (all push IP of faulting instruction) Invalid opcode 6 Divide by zero (DIV0) Alignment check 17 ($11) General Protection Fault 13 ($0D) Page Fault 14 ($0E)
43
... kernel data IVT page tbl kernel code stack free 9 8 A data 7 6 5
A code 4 3 2 1 PT entry Kernel/Supervisor User
44
... kernel data IVT page tbl kernel code stack free 9 8 A data 7 6 5
A code 4 3 2 1 PT entry Kernel/Supervisor User Read/Only User Read/Write
45
... kernel data IVT page tbl kernel code stack free 9 8 A data 7 6 5
A code 4 3 2 1 PT entry Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute
46
... kernel data IVT page tbl kernel code stack free 9 8 A data 7 6 5
A code 4 3 2 1 PT entry Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute
47
... kernel data IVT page tbl kernel code stack free 10 9 8 A data 7 6
5 A code 4 3 2 1 PT entry Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute
48
call to kernel’s AllocMem API function Non-present Kernel/Supervisor
... kernel data IVT page tbl kernel code stack free 10 9 used (RTL heap) 8 A data 7 6 5 A code 4 3 2 1 PT entry AllocMem API will return based address of a free page (9) to RTL → RTL will manage subsequent allocations in that page call to kernel’s AllocMem API function Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute call to RTL’s New(1000)
49
B A Heap state after: A := New(1000 bytes); B := New(2000 bytes); ...
kernel data IVT page tbl kernel code stack free 10 9 used (RTL heap) 8 A data 7 6 5 A code 4 3 2 1 PT entry 1072 bytes of free memory Heap mngmt record size: 1080 next: nil B 2000 bytes of allocated memory FirstFreeBlock FirstUsedBlock Heap mngmt record size: 2008 next: nil Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute A 1000 bytes of allocated memory Heap mngmt record size: 1008 next:
50
call to kernel’s AllocMem API function Non-present Kernel/Supervisor
... kernel data IVT page tbl kernel code stack free 10 used (RTL heap) 9 8 A data 7 6 5 A code 4 3 2 1 PT entry AllocMem API will return base address of next free page (10) to RTL → RTL will manage subsequent allocations in that page call to kernel’s AllocMem API function Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute 3rd call to RTL’s New(3000) – will not fit current heap (into page 9)
51
8192-3008-2008-1008 = 2168 bytes of free memory
Heap state after: A := New(1000 bytes); B := New(2000 bytes); C := New(3000 bytes); ... kernel data IVT page tbl kernel code stack free 10 used (RTL heap) 9 8 A data 7 6 5 A code 4 3 2 1 PT entry If pagesize = 4096: 2 pages = 2*4096 = 8192 bytes = 2168 bytes of free memory Heap mngmt record size: 2168 next: nil C 3000 bytes of allocated memory Heap mngmt record size: 3008 next: nil B 2000 bytes of allocated memory FirstFreeBlock FirstUsedBlock Heap mngmt record size: 2008 next: Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute A 1000 bytes of allocated memory Heap mngmt record size: 1008 next:
52
8192-3008-2008-1008 = 2168 bytes of free memory
Heap state after: A := New(1000 bytes); B := New(2000 bytes); C := New(3000 bytes); Dispose(B); ... kernel data IVT page tbl kernel code stack free 10 used (RTL heap) 9 8 A data 7 6 5 A code 4 3 2 1 PT entry If pagesize = 4096: 2 pages = 2*4096 = 8192 bytes = 2168 bytes of free memory Heap mngmt record size: 2168 next: nil C 3000 bytes of allocated memory Heap mngmt record size: 3008 next: nil B 2000 bytes of free memory FirstFreeBlock FirstUsedBlock Heap mngmt record size: 2008 next: Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute A 1000 bytes of allocated memory Heap mngmt record size: 1008 next:
53
... kernel data IVT page tbl kernel code stack free 10 used (RTL heap)
9 8 A data 7 6 5 A code 4 3 2 1 PT entry Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute
54
... kernel data IVT page tbl kernel code stack guard page free 10
used (RTL heap) 9 8 A data 7 6 5 A code 4 3 2 1 PT entry Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute
55
... kernel data IVT page tbl kernel code stack guard page free 10
used (RTL heap) 9 8 A data 7 6 5 A code 4 3 2 1 PT entry Non-present Kernel/Supervisor User Read/Only User Read/Write NX/XD No Execute
56
kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... main program of P.EXE
57
kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint call Exit clean up (release resources) ... (never here = rest of P.EXE main program) ... ret goto
58
context switch context switch kernel init call Exec(‘shell.exe’)
load shell.exe call shell.exe entrypoint ... repeat until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint call Exit clean up (release resources) ... (never here = rest of P.EXE main program) ... pop currentPID ret goto context switch context switch
59
Allocated memory (pages)
kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... AllocMem → for currentPID = 2 call Exit clean up (release resources) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) goto context switch to PID 2 context switch back to PID 1
60
Allocated memory (pages)
List of loaded DLLs kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... AllocMem → for currentPID = 2 call Exit clean up (release resources) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) goto context switch to PID 2 context switch back to PID 1
61
Allocated memory (pages)
List of loaded DLLs CPU fault → kernel interrupt handler → call procTable[currentPID].faultHandlers[faultID] kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... AllocMem → for currentPID = 2 call Exit clean up (release resources) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) goto context switch to PID 2 context switch back to PID 1
62
... kernel data IVT proc table page tbl kernel code stack guard page free A data A code PT Non-present Kernel/Supervisor User Read/Only User Read/Write
63
... kernel data IVT proc table page tbl kernel code stack guard page free A heap A data A code PT Non-present Kernel/Supervisor User Read/Only User Read/Write → Pascal runtime’s call of syscall (OS API) AllocMem
64
... kernel data IVT proc table page tbl kernel code stack guard page free A heap A data A code PT Non-present Kernel/Supervisor User Read/Only User Read/Write
65
... kernel data IVT proc table page tbl kernel code stack guard page free B heap B data B code A heap A data A code PT Non-present Kernel/Supervisor User Read/Only User Read/Write
66
... kernel data IVT proc table page tbl kernel code stack guard page free B heap B data B code A heap A data A code PT Non-present Kernel/Supervisor User Read/Only User Read/Write
67
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 PT B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 Non-present Kernel/Supervisor User Read/Only User Read/Write
68
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 PT B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 Non-present Kernel/Supervisor User Read/Only User Read/Write
69
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 PT B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 Non-present Kernel/Supervisor User Read/Only User Read/Write
70
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 PT B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 Non-present Kernel/Supervisor User Read/Only User Read/Write
71
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 PT B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 Non-present Kernel/Supervisor User Read/Only User Read/Write
72
Allocated memory (pages)
List of loaded DLLs CPU fault → kernel interrupt handler call procTable[currentPID].faultHandlers[faultID] Page table (state of the address space) kernel init call Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; procTable[currentPID].pageTable := InitilizeNewPageTable; CR3 := procTable[currentPID].pageTable; procTable[currentPID].oldSP := SP – sizeof(entrypoint’s stack frame) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint call f1 in P.EXE call f2 in P.EXE call Exit clean up (release resources) SP := procTable[currentPID].oldSP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID goto context switch to PID 2 context switch to PID 2 context switch back to PID 1
73
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 PT page 0 B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 Non-present Kernel/Supervisor User Read/Only User Read/Write
74
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 PT page 0 B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 A’s stack frames B’s stack frames Non-present Kernel/Supervisor User Read/Only User Read/Write
75
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 B heap B data B code A heap A data A code A PT page 0 B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 A’s stack frames unused A’s stack B’s stack frames Non-present Kernel/Supervisor User Read/Only User Read/Write
76
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 B heap B data B code A heap A data A code A PT page 0 B PT CPU (x86/IA-32) EIP ESP CR3 31 page table base 0 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 Non-present Kernel/Supervisor User Read/Only User Read/Write
77
Process vs. Thread Process state (context): Allocated memory (pages)
List of loaded DLLs CPU fault → kernel interrupt handler call procTable[currentPID].faultHandlers[faultID] Page table (state of the address space) PID (Process ID) Thread state (context): Call stack (allocated in context of a process) + SP register! Other CPU registers (IP, FLAGS, general register [if running]) TID (Thread ID)
78
CreateThread(@ExecStartFunc)
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 Exec CreateProcess IP 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
79
CreateThread(@ExecStartFunc)
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 Exec CreateProcess CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc IP ExecStartFunc: call DLL entrypoints call B_entrypoint ret
80
CreateThread(startFunc : pointer) newTID := AllocFreeTID;
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 IP ExecStartFunc: call DLL entrypoints call B_entrypoint ret
81
CreateThread(startFunc : pointer) newTID := AllocFreeTID;
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 B stack max SP CreateThread(startFunc : pointer) newTID := AllocFreeTID; threadTable[newTID].SP := AllocNewStack; threadTable[currTID].SP := SP; SP := threadTable[newTID].SP; currTID := newTID; jmp startFunc IP ExecStartFunc: call DLL entrypoints call B_entrypoint ret
82
CreateThread(startFunc : pointer) newTID := AllocFreeTID;
Thread A: A_entrypoint ... call A_main call funcX call Exec Thread B: SP ret from A_entry ret from A_main ret from funcX ret from Exec A stack max B stack max 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
83
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 SP ret from B_entry B stack max IP ExecStartFunc: call DLL entrypoints call B_entrypoint ret
84
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 ret from B_entry ret from funcY B stack max SP IP
85
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 ret from B_entry ret from funcY ret from Yield B stack max SP Yield: IP
86
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from B_entry ret from funcY ret from Yield B stack max SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
87
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from B_entry ret from funcY ret from Yield B stack max SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
88
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from B_entry ret from funcY ret from Yield B stack max SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
89
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from B_entry ret from funcY ret from Yield B stack max SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
90
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
91
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
92
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
93
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
94
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
95
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
96
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
97
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from funcZ B stack max SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
98
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from funcZ ret from Yield B stack max SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
99
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 ret from funcZ ret from Yield B stack max SP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret IP
100
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
101
threadTable[currTID].SP := SP; nextTID := GetNextThreadID;
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 A stack max ret from B_entry ret from funcY ret from funcZ ret from Yield B stack max SP IP Yield: threadTable[currTID].SP := SP; nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
102
We’ve Just Implemented Cooperative Multitasking
103
Scheduler Yield: threadTable[currTID].SP := SP;
nextTID := GetNextThreadID; SwitchProcessContextIfNecessary SP := threadTable[nextTID].SP; currTID := nextTID; ret
104
Preemptive Multitasking
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.