program ScheduleTest;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, Messages;
type TTaskRect = record t_esp: integer;//当前任务的esp寄存器的备份 t_eip: integer;//当前任务的eip寄存器的备份 end;
const TaskNum = 4; WaitCount = $7FFFFFFF;
var task: array[0..3] of TTaskRect; current: integer = 3;
function SetJmp(var p: TTaskRect): integer; asm mov dword ptr [p+0],esp mov ecx,dword ptr [esp] mov dword ptr [p+4],ecx mov eax,0 end;
procedure LongJmp(var p: TTaskRect; code: integer); asm mov esp,dword ptr [p+0] push ecx mov ecx,dword ptr [p+4] mov dword ptr [esp+4],ecx pop ecx mov eax,code end;
procedure schedule();//调度的核心函数 var prev, i: integer; begin prev := current; current := current + 1; if current = TaskNum then begin SetJmp(task[prev]); current := 0; LongJmp(task[current], 1); end else begin i := SetJmp(task[prev]); if i <> 0 then exit; if current >= 3 then current := 0; LongJmp(task[current], 1); end; end;
procedure wait(); var index: integer; begin for index := WaitCount downto 0 do ; end;
procedure Task0; //任务0 begin writeln('Task0 is begin....'); while true do begin schedule(); writeln(' Task0 is Running...'); wait(); end; end;
procedure Task1; //任务1 begin writeln('Task1 is begin....'); while true do begin schedule(); writeln(' Task1 is Running...'); wait(); end; end;
procedure Task2; //任务2 begin writeln('Task2 is begin....'); while true do begin schedule(); writeln(' Task2 is Running...'); wait(); end; end;
procedure Task_wait; begin while true do begin schedule(); writeln(' wait_for is Running...'); end; end;
var t_esp: integer; begin asm mov t_esp,esp //取得当前栈顶地址 end; task[0].t_esp := t_esp - 100; //这里使用一个栈的不同部分来模拟多个栈。 task[1].t_esp := t_esp - 200; //栈边界必须为4的倍数,因为栈的操作都是32位的 task[2].t_esp := t_esp - 320; task[0].t_eip := integer(@Task0); //初始化各个任务的eip初始值(开始运行的地址) task[1].t_eip := integer(@Task1); task[2].t_eip := integer(@Task2); schedule(); //开始调度 end.
|
请发表评论