1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
program StepOverPrg;
{$asmMode intel}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
sysutils, Classes;
type
{ TTestThread1 }
TTestThread1 = class(TThread)
procedure Execute; override;
end;
var
x, BreakDummy: Integer;
T1, T1Interfere: Integer;
T1Stop: Boolean;
label
testasmlbl1, testasmlbl2;
Procedure MyNorm;
begin
x := 1;
end;
Procedure StepOverEnd(a: integer);
var
b: integer;
begin
b := a;
// end returns to the same line
if a < 1 then StepOverEnd(a+1); end; // TEST_BREAKPOINT=StepOverEnd
Procedure MyNested(ALvl: Integer = 0);
var
a: integer;
begin
if ALvl > 3 then exit; a := x;
if ALvl = 0 then
x := 1; // TEST_BREAKPOINT=BrkNested
x := 3; MyNested(ALvl + 1); x := 4; if ALvl = 0 then // only reach "AfterNested" in most outer recurse
x := 2; // TEST_BREAKPOINT=AfterNested
x := 1;
end;
Procedure MySleep;
begin
Sleep(50);
end;
Procedure MyBrkDis;
begin
x := 1; // TEST_BREAKPOINT=BrkDisabled
end;
Procedure MyBrkHitCnt;
begin
x := 1; // TEST_BREAKPOINT=BrkHitCnt
end;
(* Try to step over a line, while another thread is also going through the line *)
Procedure MyInterfereByThread(a: Boolean = false);
Procedure MyInterfereSleep;
begin
if a then Sleep(10); // threads do not stop / while the test waits here, other threads should hit the calling line
end;
begin
if a then
x := 1; // TEST_BREAKPOINT=BrkInterfereByThread
if a then InterLockedExchange(T1Interfere, 0); while (InterLockedExchangeAdd(T1Interfere,0)=0) do begin MyInterfereSleep; if not a then break; end;
x := 1; // TEST_BREAKPOINT=AfterInterfereByThread
InterLockedIncrement(T1Interfere); // Other threads will increment
end;
{ TTestThread1 }
procedure TTestThread1.Execute;
begin
InterLockedIncrement(T1);
while not (Terminated or T1Stop) do MyInterfereByThread;
InterLockedDecrement(T1);
end;
begin
x := 1;
x := x + 1; // TEST_BREAKPOINT=BrkStart
x := x + 1; x := x + 2; x := x + 3; // TEST_BREAKPOINT=AfterStep
MyNorm(); // TEST_BREAKPOINT=AfterStepLongLine
x := 1; MyNorm(); x := x + 1; MyNorm(); x := x + 1; MyNorm(); x := x + 1; // TEST_BREAKPOINT=AfterStepProc
MySleep(); // TEST_BREAKPOINT=AfterStepProcLong
sleep(50); // TEST_BREAKPOINT=AfterStepSleepProc
MyBrkDis; // TEST_BREAKPOINT=AfterStepSleep
MyBrkHitCnt; // TEST_BREAKPOINT=AfterStepBrkDis
MyBrkDis; // TEST_BREAKPOINT=AfterStepBrkHitCnt
x := 1; // TEST_BREAKPOINT=AfterStepBrkDisAgain
x := 1;
MyNested; // TEST_BREAKPOINT=CallNested
T1 := 0;
T1Stop := False;
TTestThread1.Create(False); while not (InterLockedExchangeAdd(T1,0)=1) do x:=1; // TEST_BREAKPOINT=BrkThreadCreateInStep
x := 1; // TEST_BREAKPOINT=AfterThreadCreateInStep
(* Prepare for threads to interfare with the hidden breakpoint *)
// create a few threads to interfer
TTestThread1.Create(False); TTestThread1.Create(False); TTestThread1.Create(False);
TTestThread1.Create(False); TTestThread1.Create(False); TTestThread1.Create(False);
while not (InterLockedExchangeAdd(T1,0)>=5) do sleep(10); // at least 5 running
MyInterfereByThread(True);
T1Stop := True;
while not (InterLockedExchangeAdd(T1,0)<=1) do x:=1; // TEST_BREAKPOINT=BrkThreadExitInStep
x := 1; // TEST_BREAKPOINT=AfterThreadExitInStep
//sleep(500);
BreakDummy := 1;
StepOverEnd(0); // TEST_BREAKPOINT=CallStepOverEnd
BreakDummy := 1; // TEST_BREAKPOINT=AfterCallStepOverEnd
BreakDummy := 1;
end.
|