您现在的位置:首页 >> 基础算法 >> window基础 >> 内容

Delphi中任务调度的模拟多线程/任务

时间:2011/9/3 15:32:17 点击:

  核心提示:programScheduleTest;{$APPTYPECONSOLE}usesSysUtils,Windows,Messages;typeTTaskRect=recordt_esp:integer...
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.
由于这只是一个简单的测试,所以在setjmp函数中并没有备份当前环境下的ebp寄存器(其他的寄存器都没有保存!),所以这里的子任务都不允许使用内部变量!

作者:网络 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 盒子文章(www.2ccc.com) © 2022 版权所有 All Rights Reserved.
  • 沪ICP备05001939号