Windows.HierarchicalProfiler0.Mod 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. MODULE HierarchicalProfiler0; (** AUTHOR "staubesv"; PURPOSE "WinAos platform-specific part of the hierarchical profiler"; *)
  2. IMPORT
  3. SYSTEM, Kernel32, Objects, Modules, ProcessInfo;
  4. CONST
  5. Initialized = 0;
  6. Running = 1;
  7. Terminating = 2;
  8. Terminated = 3;
  9. Intervall = 1; (* milliseconds *)
  10. TYPE
  11. ProcessTimeArray = POINTER TO ARRAY ProcessInfo.MaxNofProcesses OF HUGEINT;
  12. Callback = PROCEDURE (id : LONGINT; process : Objects.Process; pc, bp, lowAdr, highAdr : ADDRESS);
  13. Poller = OBJECT
  14. VAR
  15. processes, oldProcesses : ARRAY ProcessInfo.MaxNofProcesses OF Objects.Process;
  16. nofProcesses, oldNofProcesses : LONGINT;
  17. times, oldTimes : ProcessTimeArray;
  18. me : Objects.Process;
  19. state : LONGINT;
  20. PROCEDURE &Init;
  21. BEGIN
  22. state := Running;
  23. ProcessInfo.Clear(processes); nofProcesses := 0;
  24. ProcessInfo.Clear(oldProcesses); oldNofProcesses := 0;
  25. NEW(times); Clear(times);
  26. NEW(oldTimes); Clear(oldTimes);
  27. END Init;
  28. PROCEDURE Terminate;
  29. BEGIN {EXCLUSIVE}
  30. IF (state # Terminated) THEN state := Terminating; END;
  31. AWAIT(state = Terminated);
  32. END Terminate;
  33. PROCEDURE Clear(array : ProcessTimeArray);
  34. VAR i : LONGINT;
  35. BEGIN
  36. FOR i := 0 TO LEN(array)-1 DO array[i] := 0; END;
  37. END Clear;
  38. PROCEDURE RanMeanwhile(process : Objects.Process; currentCycles : HUGEINT) : BOOLEAN;
  39. VAR i : LONGINT;
  40. BEGIN
  41. IF ~(process.mode IN {Objects.Running,Objects.Ready}) THEN RETURN FALSE END;
  42. i := 0; WHILE (i < oldNofProcesses) & (oldProcesses[i] # process) DO INC(i); END;
  43. RETURN (i >= oldNofProcesses) OR (oldTimes[i] < currentCycles);
  44. END RanMeanwhile;
  45. PROCEDURE Process;
  46. VAR process : Objects.Process; cycles : Objects.CpuCyclesArray; temp : ProcessTimeArray; i : LONGINT;
  47. t0,t1,t2,t3: Kernel32.FileTime;
  48. BEGIN
  49. ProcessInfo.GetProcesses(processes, nofProcesses);
  50. FOR i := 0 TO nofProcesses - 1 DO
  51. process := processes[i];
  52. Objects.GetCpuCycles(process, cycles, FALSE); (* higher granularity counter, but does not detect suspending of thread *)
  53. times[i] := cycles[0];
  54. (*
  55. Kernel32.GetThreadTimes(process.handle, t0,t1,t2,t3);
  56. times[i] := HUGEINT(t2.dwLowDateTime+t3.dwLowDateTime) + 10000000H * HUGEINT(t2.dwHighDateTime+t3.dwHighDateTime) ;
  57. *)
  58. IF (process # me) & (cycles[0] # 0) & (process.mode = Objects.Running) (* (process.mode # Objects.AwaitingEvent) & (process.mode # Objects.AwaitingCond) & (process.mode < Objects.Suspended) & (process.mode >= Objects.Ready) (*RanMeanwhile(process, times[i]) *) *) THEN
  59. HandleProcess(process);
  60. END;
  61. END;
  62. temp := oldTimes;
  63. oldTimes := times;
  64. times := temp;
  65. ProcessInfo.Copy(processes, oldProcesses); oldNofProcesses := nofProcesses;
  66. ProcessInfo.Clear(processes);
  67. END Process;
  68. BEGIN {ACTIVE, PRIORITY(Objects.Realtime)}
  69. me := Objects.CurrentProcess();
  70. LOOP
  71. WHILE (state = Running) DO
  72. Process;
  73. (*Kernel32.Sleep(Intervall);*)
  74. END;
  75. IF (state = Terminating) THEN EXIT; END;
  76. END;
  77. ProcessInfo.Clear(processes);
  78. ProcessInfo.Clear(oldProcesses);
  79. BEGIN {EXCLUSIVE} state := Terminated; END;
  80. END Poller;
  81. VAR
  82. poller : Poller;
  83. callback : Callback;
  84. state : LONGINT;
  85. PROCEDURE HandleProcess(process : Objects.Process);
  86. VAR context : Kernel32.Context; handle : Kernel32.HANDLE; res : Kernel32.BOOL; stackBottom, sp, bp: ADDRESS;
  87. BEGIN
  88. ASSERT(process # NIL);
  89. handle := process.handle;
  90. IF (handle # Kernel32.NULL) & (handle # Kernel32.InvalidHandleValue) THEN
  91. res := Kernel32.SuspendThread(handle);
  92. IF (res >= 0) THEN
  93. context.ContextFlags := Kernel32.ContextControl+Kernel32.ContextInteger;
  94. res := Kernel32.GetThreadContext(handle, context);
  95. IF (res = Kernel32.True) THEN
  96. IF (context.PC # 0) THEN
  97. stackBottom := Objects.GetStackBottom(process);
  98. bp := context.BP;
  99. sp := context.SP;
  100. ASSERT(context.BP <= stackBottom);
  101. callback(1, process, context.PC, context.BP, context.SP, stackBottom(* LONGINT(0FFFFFFFFH)*) );
  102. END;
  103. END;
  104. res := Kernel32.ResumeThread(handle);
  105. END;
  106. END;
  107. END HandleProcess;
  108. PROCEDURE Enable*(proc : Callback);
  109. BEGIN {EXCLUSIVE}
  110. ASSERT(proc # NIL);
  111. ASSERT((state = Initialized) & (poller = NIL));
  112. callback := proc;
  113. NEW(poller);
  114. state := Running;
  115. END Enable;
  116. PROCEDURE Disable*;
  117. BEGIN {EXCLUSIVE}
  118. ASSERT((state = Running) & (poller # NIL));
  119. poller.Terminate;
  120. poller := NIL;
  121. state := Initialized;
  122. END Disable;
  123. PROCEDURE Cleanup;
  124. BEGIN
  125. IF (poller # NIL) THEN poller.Terminate; poller := NIL; END;
  126. END Cleanup;
  127. BEGIN
  128. state := Initialized;
  129. Modules.InstallTermHandler(Cleanup);
  130. END HierarchicalProfiler0.
  131. WMProfiler.Open
  132. SystemTools.Free WMProfiler HierarchicalProfiler HierarchicalProfiler0 ~
  133. Debugging.DisableGC~