1 / 26

Practical Session 7

Computer Architecture and Assembly Language. Practical Session 7. 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 :

mhallman
Download Presentation

Practical Session 7

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Computer Architecture and Assembly Language Practical Session 7

  2. 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()

  3. 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 currentstatebefore it suspends itself (in order to continue its execution later) • stack state • registers • flags • stack pointer (ESP) • instructions pointer (EIP)

  4. 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 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 co-routine stack

  5. STKSZ equ 16*1024 ; co-routine stack size CODEP 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 16 global numco numco: dd 3 CORS: dd CO1 dd CO2 dd CO3section .data align 16 CO1: dd Function1 ; structure for first co-routine Flags1: dd 0 SP1: dd STK1+STKSZ CO2: dd Function1 ; structure for second co-routine Flags2: dd 0 SP2: dd STK2+STKSZ CO3: dd Function2 ; structure for third co-routine Flags3: dd 0 SP3: dd STK3+STKSZ section .bss align 16 CURR: resd 1 SPT: resd 1 ; temporary stack pointer variable SPMAIN: resd 1 ; stack pointer of main STK1: resb STKSZ STK2: resb STKSZ STK3: resb STKSZ Variables Declaration

  6. Co-routine initialization - save initial co-routine state 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); } 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

  7. Co-routine initialization - save initial co-routine state 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); } 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) … ESP co-routine structure co-routine stack

  8. Co-routine initialization - save initial co-routine state 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); } 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) … ESP co-routine structure co-routine stack

  9. Co-routine initialization - save initial co-routine state 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); } 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) … ESP co-routine structure co-routine stack

  10. Co-routine initialization - save initial co-routine state 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); } 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) … ESP co-routine structure co-routine stack

  11. Co-routine initialization - save initial co-routine state 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); } 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) … ESP co-routine structure co-routine stack

  12. Co-routine initialization section .text align 16 extern printf global init_co_from_c global start_co_from_c global end_co init_co_from_c: push EBP mov EBP, ESP push EBX mov EBX, [EBP+8] ; EBX contains a number of the co-routine to be initialized mov EBX, [EBX*4+CORS] ; EBX contains a pointer to co-routine structure to be initialized call co_init pop EBX pop EBP ret co_init: pushad bts dword [EBX+FLAGSP],0 ; test if already initialized jc init_done mov EAX,[EBX+CODEP] ; get initial PC mov [SPT], ESP ; save original SP mov ESP,[EBX+SPP] ; get initial SP mov EBP, ESP ; also use as EBP push EAX ; push initial "return" address (initial PC) pushfd ; push flags pushad ; push all other registers mov [EBX+SPP],ESP ; save new SP in structure mov ESP, [SPT] ; restore original SP init_done: popad ret ‘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.

  13. Start co-routine scheduler We 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); }

  14. Scheduler co-routine function Scheduler 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 caller pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP ; save current SP do_resume: ; load SP for resumedco-routine mov ESP, [EBX+SPP] mov [CURR], EBX popad ; restore resumed co-routine state popfd ret ; "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

  15. Function2 This function used as code for co-routine 3 (scheduler) FMT2: db "Function2, co %lx, called by %lx, pass %ld", 10, 0 Function2: push dword 1 push dword [CORS] ; indeed, called by main push dword [CURR] push dword FMT2 call printf add ESP, 16 mov EBX, [CORS] ; resume CO1 call resume push dword 2 push dword [CORS] push dword [CURR] push dword FMT2 call printf add ESP, 16 mov EBX, [CORS+4] ; resume CO2 call resume push dword 3 push dword [CORS+4] push dword [CURR] push dword FMT2 call printf add ESP, 16 mov EBX, [CORS] ; resume CO1 call resume push dword 4 push dword [CORS] push dword [CURR] push dword FMT2 call printf add ESP, 16 mov EBX, [CORS+4] ; resume CO2 call resume jmp end_co ; resume main

  16. 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 1 push dword [CORS+8] push dword [CURR] push dword FMT1 call printf add ESP, 16 mov EBX, [CORS+8] ; resume a scheduler call resume push dword 2 push dword [CORS+8] push dword [CURR] push dword FMT1 call printf add ESP, 16 mov EBX, [CORS+8] ; resume a scheduler call resume

  17. Run example – data declaration .bss .data

  18. Afterco-routine initialization .bss .data

  19. Resuming - right before .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  20. Resuming – resume is called .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  21. Resuming – backup registers .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  22. Resuming – backup stack pointer .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  23. Resuming - load stack pointer of resume co-routine .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  24. Resuming – set current co-routine variable .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  25. Resuming – restore a state of loaded co-routine .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

  26. Resuming – go to execute the loaded co-routine .bss .data resume: pushfd pushad mov EDX, [CURR] mov [EDX+SPP],ESP do_resume: mov ESP, [EBX+SPP] mov [CURR], EBX popad popfd ret ESP

More Related