computer architecture and assembly languagecaspl162/wiki.files/ps07_162[1].pdf · main() scheduler...
TRANSCRIPT
Co-Routines
• co-routines are assembly
implementation of threads
• each co-routine decides to which co-routine
to pass a control (unlike “usual” threads)
We would implement “silly” round robin scheduling algorithm:
main() scheduler co-routine1 scheduler co-routine2 scheduler
co-routine1 scheduler co-routine2 scheduler main()
Co-routine state• co-routine is denoted by Coi (i is co-routine’s id)
• scheduler is also a co-routine
• co-routine suspends itself after some “time slice”
• co-routine resumes a scheduler
• co-routine should save its current state before it
suspends itself (in order to continue its execution later)
• stack state
• registers
• flags
• stack pointer (ESP)
• instructions pointer (EIP)
Co-routine structure
STKSIZE equ 16*1024 ;(16 Kb)
STKi: resb STKSIZE
COi: dd Functioni ; pointer to co-routine function
Flags: dd 0 ; 0 if co-routine is not initialized, 1 otherwise
SPi: dd STKi + STKSIZE ; pointer to the beginning of co-routine stack
Co-routine structure:
We define an array of co-routines’ structures:
why SPi points to the end of stack ?
to be able to use push and pop stack functionality with ESP
SPi0Funci
co-routine structure co-routine stack
STKSZ equ 16*1024 ; co-routine stack sizeCODEP equ 0 ; offset of pointer to co-routine function in co-routine structure FLAGSP equ 4 ; offset of pointer to flags co-routine structure SPP equ 8 ; offset of pointer to co-routine stack in co-routine structure section .rodata
align 16global numco
numco: dd 3CORS: dd CO1
dd CO2dd CO3
section .dataalign 16
CO1: dd Function1 ; structure for first co-routineFlags1: dd 0SP1: dd STK1+STKSZCO2: dd Function1 ; structure for second co-routineFlags2: dd 0SP2: dd STK2+STKSZCO3: dd Function2 ; structure for third co-routineFlags3: dd 0SP3: dd STK3+STKSZsection .bss
align 16CURR: resd 1SPT: resd 1 ; temporary stack pointer variableSPMAIN: resd 1 ; stack pointer of mainSTK1: resb STKSZSTK2: resb STKSZSTK3: resb STKSZ
Variables Declaration
SPi0Funci
Co-routine initialization - save initial co-routine state
co_init:
…
mov eax, [ebx+CODEP] ; get initial PC
…
mov esp, [EBX+SPP] ; get initial SP
…
push eax ; push initial “return” address
pushfd ; push flags
pushad ; push all other registers
mov [ebx+SPP], esp ; save new SPi value (after all the pushes)
…
co-routine structure co-routine stack
init_co_from_c:
…
mov ebx, [ebp+8] ; get co-routine ID number
mov ebx, [4*ebx + CORS] ; get COi pointer
call co_init
…
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
SPi0Funci
Co-routine initialization - save initial co-routine state
co_init:
…
mov eax, [ebx+CODEP] ; get initial PC
…
mov esp, [EBX+SPP] ; get initial SP
…
push eax ; push initial “return” address
pushfd ; push flags
pushad ; push all other registers
mov [ebx+SPP], esp ; save new SPi value (after all the pushes)
…
co-routine structure co-routine stack
init_co_from_c:
…
mov ebx, [ebp+8] ; get co-routine ID number
mov ebx, [4*ebx + CORS] ; get COi pointer
call co_init
…
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
ESP
FunciSPi0Funci
Co-routine initialization - save initial co-routine state
co_init:
…
mov eax, [ebx+CODEP] ; get initial PC
…
mov esp, [EBX+SPP] ; get initial SP
…
push eax ; push initial “return” address
pushfd ; push flags
pushad ; push all other registers
mov [ebx+SPP], esp ; save new SPi value (after all the pushes)
…
co-routine structure co-routine stack
init_co_from_c:
…
mov ebx, [ebp+8] ; get co-routine ID number
mov ebx, [4*ebx + CORS] ; get COi pointer
call co_init
…
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
ESP
FunciEFlagsSPi0Funci
Co-routine initialization - save initial co-routine state
co_init:
…
mov eax, [ebx+CODEP] ; get initial PC
…
mov esp, [EBX+SPP] ; get initial SP
…
push eax ; push initial “return” address
pushfd ; push flags
pushad ; push all other registers
mov [ebx+SPP], esp ; save new SPi value (after all the pushes)
…
co-routine structure co-routine stack
init_co_from_c:
…
mov ebx, [ebp+8] ; get co-routine ID number
mov ebx, [4*ebx + CORS] ; get COi pointer
call co_init
…
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
ESP
FunciEFlagsregistersSPi0Funci
Co-routine initialization - save initial co-routine state
co_init:
…
mov eax, [ebx+CODEP] ; get initial PC
…
mov esp, [EBX+SPP] ; get initial SP
…
push eax ; push initial “return” address
pushfd ; push flags
pushad ; push all other registers
mov [ebx+SPP], esp ; save new SPi value (after all the pushes)
…
co-routine structure co-routine stack
init_co_from_c:
…
mov ebx, [ebp+8] ; get co-routine ID number
mov ebx, [4*ebx + CORS] ; get COi pointer
call co_init
…
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
ESP
FunciEFlagsregistersSPi1Funci
Co-routine initialization - save initial co-routine state
co_init:
…
mov eax, [ebx+CODEP] ; get initial PC
…
mov esp, [EBX+SPP] ; get initial SP
…
push eax ; push initial “return” address
pushfd ; push flags
pushad ; push all other registers
mov [ebx+SPP], esp ; save new SPi value (after all the pushes)
…
co-routine structure co-routine stack
init_co_from_c:
…
mov ebx, [ebp+8] ; get co-routine ID number
mov ebx, [4*ebx + CORS] ; get COi pointer
call co_init
…
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
ESP
Co-routine initializationsection .text
align 16extern printfglobal init_co_from_cglobal start_co_from_cglobal end_co
init_co_from_c:push EBPmov EBP, ESPpush EBXmov EBX, [EBP+8] ; EBX contains a number of the co-routine to be initializedmov EBX, [EBX*4+CORS] ; EBX contains a pointer to co-routine structure to be initializedcall co_initpop EBXpop EBPret
co_init:pushadbts dword [EBX+FLAGSP],0 ; test if already initializedjc init_donemov EAX,[EBX+CODEP] ; get initial PCmov [SPT], ESP ; save original SPmov ESP,[EBX+SPP] ; get initial SPmov EBP, ESP ; also use as EBPpush EAX ; push initial "return" address (initial PC)pushfd ; push flagspushad ; push all other registersmov [EBX+SPP],ESP ; save new SP in structuremov ESP, [SPT] ; restore original SP
init_done:popadret ‘bts’ instruction tests one bit of its first operand, whose index is
given by the second operand, and stores the value of that bit in
the carry flag (CF). In addition, ‘bts’ sets the bit to be 1.
Start co-routine schedulerWe start scheduling by suspending main() and resuming a scheduler co-routine.
start_co_from_c:push EBP
mov EBP, ESP
pushad
mov [SPMAIN], ESP ; save ESP of main ()
mov EBX, [EBP+8] ; gets ID number of a scheduler
mov EBX, [EBX*4 + CORS] ; gets a pointer to a scheduler structure
jmp do_resume ; resume a scheduler co-routine
We end scheduling by going back to main().
end_co:mov ESP, [SPMAIN] ; restore state of main code
popad
pop EBP
ret
main() {
/* initialize co-routines*/
for(i = 0; i < numco; i++)
init_co_from_c(i);
/* start a scheduler co-routine*/
start_co_from_c (2);
}
Scheduler co-routine functionScheduler function is started by main.
scheduler_Function:
pick up some thread ID i
mov EBX, [CORS + i*4] ; resumes Coi
call resume
pick up some other thread ID j
mov EBX, [CORS + j*4] ; resumes Coj
call resume…
jmp end_co ; resume main
‘call resume’•save a state of the current co-routine•resume a state of the next co-routine (EBX should contain a pointer to it)
EBX is pointer to co-init structure of the co-routine to be resumed.CURR holds a pointer to co-init structure of the current co-routine.
resume: ; save state of callerpushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP ; save current SP
do_resume: ; load SP for resumed co-routinemov ESP, [EBX+SPP]mov [CURR], EBXpopad ; restore resumed co-routine statepopfdret ; "return" to resumed co-routine!
•after ‘call resume’ return address (i.e. EIP) is pushed automatically into (co-routine) stack•we only have to save EFLAGS, ESP, and registers
Function2This function used as code for co-routine 3 (scheduler)
FMT2: db "Function2, co %lx, called by %lx, pass %ld", 10, 0
Function2:push dword 1push dword [CORS] ; indeed, called by mainpush dword [CURR]push dword FMT2call printfadd ESP, 16mov EBX, [CORS] ; resume CO1call resume
push dword 2push dword [CORS]push dword [CURR]push dword FMT2call printfadd ESP, 16
mov EBX, [CORS+4] ; resume CO2call resumepush dword 3push dword [CORS+4]push dword [CURR]push dword FMT2call printfadd ESP, 16mov EBX, [CORS] ; resume CO1call resumepush dword 4push dword [CORS]push dword [CURR]push dword FMT2call printfadd ESP, 16mov EBX, [CORS+4] ; resume CO2call resumejmp end_co ; resume main
Function1
This function used as code for co-routines 1 and 2
FMT1: db "Function1, co %lx, called by %lx, pass %ld", 10, 0
Function1:push dword 1push dword [CORS+8]push dword [CURR]push dword FMT1call printfadd ESP, 16mov EBX, [CORS+8] ; resume a schedulercall resume
push dword 2push dword [CORS+8]push dword [CURR]push dword FMT1call printfadd ESP, 16mov EBX, [CORS+8] ; resume a schedulercall resume
Run example – data declaration
CURR
SPT
SPMAIN
STK1
STK2
STK3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
0 Flags1
SP1
Function1 CO2
0 Flags2
SP2
Function2 CO3
0 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
After co-routine initialization
CURR
SPT
SPMAIN
STK1
Registers
Flags
Function1
STK2
Registers
Flags
Function1
STK3
Registers
Flags
Function2
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
Resuming - right before
CO2 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
STK2
……….
……….
STK3
Registers
Flags
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
.bss .data
ESP
Resuming – resume is called
CO2 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
STK2
Addr2
……….
……….
STK3
Registers
Flags
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP
Resuming – backup registers
CO2 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
Registers STK2
Flags
Addr2
……….
……….
STK3
Registers
Flags
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP
Resuming – backup stack pointer
CO2 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
Registers STK2
Flags
Addr2
……….
……….
STK3
Registers
Flags
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP
Resuming - load stack pointer of resume co-routine
CO2 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
Registers STK2
Flags
Addr2
……….
……….
STK3
Registers
Flags
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP
Resuming – set current co-routine variable
CO3 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
Registers STK2
Flags
Addr2
……….
……….
STK3
Registers
Flags
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP
Resuming – restore a state of loaded co-routine
CO3 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
Registers STK2
Flags
Addr2
……….
……….
STK3
Addr3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP
Resuming – go to execute the loaded co-routine
CO3 CURR
SPT
SPMAIN
STK1
Registers
Flags
Addr1
Registers STK2
Flags
Addr2
……….
……….
STK3
3 numco
CO1 CORS
CO2
CO3
Function1 CO1
1 Flags1
SP1
Function1 CO2
1 Flags2
SP2
Function2 CO3
1 Flags3
SP3
0 COUNTER
3 MAX_ITER
.bss .data
resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP
do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret
ESP