/* * Multithread demo program. * Hebrew University OS course. * * Questions: os@cs.huji.ac.il */ #include #include #include #include #include #include #define SECOND 1000000 #define JB_SP 4 #define JB_PC 5 #define STACK_SIZE 4096 char stack1[STACK_SIZE]; char stack2[STACK_SIZE]; sigjmp_buf jbuf[2]; void switchThreads(); void f() { int i=0; while(1) { ++i; printf("in f (%d)\n",i); if (i % 3 == 0) { printf("f: switching\n"); switchThreads(); } usleep(SECOND); } } void g() { int i=0; while(1){ ++i; printf("in g (%d)\n",i); if (i % 5 == 0) { printf("g: switching\n"); switchThreads(); } usleep(SECOND); } } //A translation required when using an address of a variable //Use this as a black box in your code. unsigned int translate_address(unsigned int addr) { unsigned int ret; asm volatile("xor %%gs:0x18,%0\n" "rol $0x9,%0\n" : "=g" (ret) : "0" (addr)); return ret; } void setup() { unsigned int sp, pc; sp = (unsigned int)stack1 + STACK_SIZE - sizeof(int); pc = (unsigned int)f; sigsetjmp(jbuf[0],1); (jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp); (jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc); sigemptyset(&jbuf[0]->__saved_mask); sp = (unsigned int)stack2 + STACK_SIZE - sizeof(int); pc = (unsigned int)g; sigsetjmp(jbuf[1],1); (jbuf[1]->__jmpbuf)[JB_SP] = translate_address(sp); (jbuf[1]->__jmpbuf)[JB_PC] = translate_address(pc); sigemptyset(&jbuf[1]->__saved_mask); } void switchThreads() { static int currentThread = 0; int ret_val = sigsetjmp(jbuf[currentThread],1); printf("SWITCH: ret_val=%d\n", ret_val); if (ret_val == 1) { return; } currentThread = 1 - currentThread; siglongjmp(jbuf[currentThread],1); } int main() { setup(); siglongjmp(jbuf[0],1); return 0; }