分类:
2012-04-27 11:22:29
原文地址:用setjmp和longjmp实现协作式多任务 作者:xiaosuo
#include #include #include #define STACK_SIZE 1024 #define TASK_NUM 256 #define LINUX #ifdef LINUX #if !defined(JB_PC) && !defined(JB_SP) #define JB_PC 5 #define JB_SP 4 #define PTR_MANGLE(var) asm ("xorl %%gs:0x18, %0" : "=r"(var) : "0" (var)) #else #define PTR_MANGLE(var) #endif #define EIP buf[0].__jmpbuf[JB_PC] #define ESP buf[0].__jmpbuf[JB_SP] #else #define EIP buf[5]; #define ESP buf[4]; #endif typedef unsigned long ulong; typedef long task_t; typedef void (*task_func) (void *args); typedef struct task_struct{ jmp_buf buf; int used; ulong stack[STACK_SIZE]; } task_struct; static task_struct tasks[TASK_NUM]; static task_t current = 0; int task_struct_init(void) { int i; for(i = 0; i < TASK_NUM; i ++) tasks[i].used = 0; // create the first task, run in the main function. tasks[0].used = 1; return 0; } int task_create(task_t *pid, task_func func, void *args) { static int i; // find a unused task_struct for(i = 0; i < TASK_NUM; i ++){ if(!tasks[i].used){ break; } } // found none if(i == TASK_NUM) return -1; setjmp(tasks[i].buf); tasks[i].stack[STACK_SIZE - 1] = (ulong)args; tasks[i].ESP = (ulong)(tasks[i].stack + STACK_SIZE - 2); PTR_MANGLE(tasks[i].ESP); tasks[i].EIP = (ulong)func; PTR_MANGLE(tasks[i].EIP); tasks[i].used = 1; if(pid != NULL){ *pid = i; } return 0; } int task_exit(void) { tasks[current].used = 0; schedule(); } // return the current pid task_t gettid(void) { return current; } // select a task to run // return 1 when return to the last task int schedule(void) { // save the task runtime information if(setjmp(tasks[current].buf)){ return 1; } // select a active task to run while(1){ current = (current + 1) % TASK_NUM; if(tasks[current].used){ break; } } // run the task longjmp(tasks[current].buf, 1); return 0; } void t1(const char *ptr) { int i; char ch[128]; for(i = 0; i < 128; i ++){ ch[i] = '0'; printf("task %d: %s.\n", gettid(), ptr); schedule(); } task_exit(); } void t2(const char *ptr) { while(1){ printf("task %d: %s.\n", gettid(), ptr); // try to add a new task task_create(NULL, (task_func)&t1, "one(in two)"); schedule(); } } void t3(const char *ptr) { char *buf; while(1){ buf = (char*)malloc(256); printf("task %d: %s.\n", gettid(), ptr); // printf("Please input sth. :"); // scanf("%s", buf); // printf("Your input is : %s\n", buf); free(buf); schedule(); } } int main(void) { task_struct_init(); task_create(NULL, (task_func)&t1, "one"); task_create(NULL, (task_func)&t2, "two"); task_create(NULL, (task_func)&t3, "three"); while(1){ printf("task %d: core.\n", gettid()); schedule(); } return 0; } |
#define LINUX |