动手写操作系统 -- 多任务调度


接下来就是编写通用调度代码了,可以支持多个任务。

下面的例子是3个独立的任务,系统运行如下:

代码下载:funnyos_task_schedule.zip

typedef struct osTask {
	void (*ptask)(void);
	int stack_SS;
	int stack_SP;
	int isTaskStart;
} osTask;
int taskCount = 0;
int isTaskAllStart = 0;

osTask task[4];//task1, task2;

void  main (void) {
    PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);      /* Clear the screen                         */

    PC_DispStr( 0,  0, "                                  Funny OS Demo                                 ", DISP_FGND_WHITE + DISP_BGND_RED + DISP_BLINK);
	PC_SetTickRate(18);                      /* Reprogram tick rate                      */
	PC_TickISR = &TickISR;
	PC_VectSet(0x8, PC_TickISR); //asm {int 08h};

	task[0].ptask = &testTask1;       //创建任务1,任务栈地址0x90100
	task[0].stack_SS = 0x9000;
	task[0].stack_SP = 0x100;
	taskCount++;
	
	task[1].ptask = &testTask2;       //创建任务2,任务栈地址0x80100
	task[1].stack_SS = 0x8000;
	task[1].stack_SP = 0x100;
	taskCount++;

	task[2].ptask = &testTask3;       //创建任务2,任务栈地址0x70100
	task[2].stack_SS = 0x7000;
	task[2].stack_SP = 0x100;
	taskCount++;
	
	for(;;);
}

void TickISR(void) {
	static int i = 0;
	//static int j = 0;
	static int taskid = 0;
	static int taskSS, taskSP;
		
	asm {pop di; pop si;}
	asm cli;
	//outp(0x20,  0x20); 
	asm {
		push ax;
		push dx;
		mov dx,0x20;
		mov al,0x20;
		out dx,al;
		mov al,0x0;
		pop dx;
		pop ax;
	}
	asm sti;

	for(i = 0; i < taskCount; i++) {
		if(!task[i].isTaskStart) {
			task[i].isTaskStart = 1;
			
			//save pre task stack
			if(i) {
				asm {
					push ax; push bx; push cx; push dx; push si; push di; push bp; push ds; push es;
					mov taskSP, sp;
					mov taskSS, ss;
				};
				task[i-1].stack_SS = taskSS;
				task[i-1].stack_SP = taskSP;
			}
			
			taskSS = task[i].stack_SS;
			taskSP = task[i].stack_SP;
			asm {
				mov ss, taskSS;
				mov sp, taskSP;
			}
			(*(task[i].ptask))();
		}
	}
	if(!isTaskAllStart) {
		isTaskAllStart = 1;
		taskid = taskCount - 1; //taskid starts from 0
	}
	
	for(i = 0; i < taskCount; i++) {
		if(i == taskid) {
			//save task stack
			asm {
				push ax; push bx; push cx; push dx; push si; push di; push bp; push ds; push es;
				mov taskSP, sp;
				mov taskSS, ss;
			};
			task[i].stack_SS = taskSS;
			task[i].stack_SP = taskSP;

			//restore nextTaskid stack
			taskid = ((taskid+1) == taskCount) ? (0) : (taskid + 1);  //taskid = next task id
			taskSS = task[taskid].stack_SS;
			taskSP = task[taskid].stack_SP;
			asm {
				mov ss, taskSS;
				mov sp, taskSP;
				pop es; pop ds; pop bp; pop di; pop si; pop dx; pop cx; pop bx; pop ax;
				iret;
			}
		}
	}
	//asm iret;
}

上篇: 动手写操作系统 -- 任务切换(独立栈) 下篇: 动手写操作系统 -- 排序算法可视化比较