#include #include #include struct float_reg { long cwd; long swd; long twd; long fip; long fcs; long foo; long fos; long st_space[20]; long status; }; struct user_regs { int ebx; int ecx; int edx; int esi; int edi; int ebp; int eax; int esp; int eip; struct float_reg fp_status; }; #define SAVE_REGS(regs) \ asm("movl %%ebx, %0\n\t" \ "movl %%ecx, %1\n\t" \ "movl %%edx, %2\n\t" \ "movl %%esi, %3\n\t" \ "movl %%edi, %4\n\t" \ "movl %%eax, %5\n\t" \ "fsave %6\n\t" \ "movl $1f, %7\n\t" \ "movl %%esp, %8\n\t" \ "movl %%ebp, %9\n\t" \ "1:\n\t"\ :: \ "m"(regs.ebx),\ "m"(regs.ecx),\ "m"(regs.edx), \ "m"(regs.esi), \ "m"(regs.edi), \ "m"(regs.eax), \ "m"(regs.fp_status),\ "m"(regs.eip),\ "m"(regs.esp),\ "m"(regs.ebp)) #define RESTORE_REGS(regs) \ asm("movl %0, %%ebx\n\t" \ "movl %1,%%ecx\n\t" \ "movl %2,%%edx\n\t" \ "movl %3,%%esi\n\t" \ "movl %4,%%edi\n\t" \ "movl %5,%%eax\n\t" \ "movl %6,%%esp\n\t"\ "movl %7,%%ebp\n\t"\ "frstor %8\n\t"\ "pushl %9\n\t"\ "ret\n\t"\ : "=m"((regs).ebx),\ "=m"((regs).ecx),\ "=m"((regs).edx), \ "=m"((regs).esi), \ "=m"((regs).edi), \ "=m"((regs).eax), \ "=m"((regs).esp),\ "=m"((regs).ebp),\ "=m"((regs).fp_status),\ "=m"((regs).eip)) #define NUM_FUNCS 2 #define STACK_SIZE 0xffff struct user_regs regs[2]; struct user_regs temp_reg; int func=0; int called_once[NUM_FUNCS]; char * func_stack; void func_B(); void switch_to() { int temp; func=1-func; temp=func; SAVE_REGS(temp_reg); if(func == temp) { regs[1-func]=temp_reg; if(!called_once[1] && func==1) { asm("movl %0,%%esp\n\t"\ : "=m"(func_stack)); called_once[func]=1; func_B(); exit(1); // not reached } else { temp_reg=regs[func]; RESTORE_REGS(temp_reg); } } } void my_sleep(int secs) { sleep(secs); switch_to(); } void func_A() { register int i=0; while(1) { printf("In function A:%d\n",i); i += 1; my_sleep(2); } } void func_B() { register int i=0; while(1) { printf("In function B:%d\n",i); i += 1; my_sleep(2); } } int init_stack() { int i; called_once[0]=1; for(i=1;i