Unix.HierarchicalProfiler0.Mod 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. MODULE HierarchicalProfiler0; (** AUTHOR "skoster"; PURPOSE "UnixAOS platform-specific part of the hierarchical profiler"; *)
  2. IMPORT
  3. SYSTEM, Kernel, Unix, 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. timer: Kernel.Timer;
  21. PROCEDURE &Init;
  22. BEGIN
  23. state := Running;
  24. ProcessInfo.Clear(processes); nofProcesses := 0;
  25. ProcessInfo.Clear(oldProcesses); oldNofProcesses := 0;
  26. NEW(times); Clear(times);
  27. NEW(oldTimes); Clear(oldTimes);
  28. END Init;
  29. PROCEDURE Terminate;
  30. BEGIN {EXCLUSIVE}
  31. IF (state # Terminated) THEN state := Terminating; END;
  32. AWAIT(state = Terminated);
  33. END Terminate;
  34. PROCEDURE Clear(array : ProcessTimeArray);
  35. VAR i : LONGINT;
  36. BEGIN
  37. FOR i := 0 TO LEN(array)-1 DO array[i] := 0; END;
  38. END Clear;
  39. PROCEDURE RanMeanwhile(process : Objects.Process; currentCycles : HUGEINT) : BOOLEAN;
  40. VAR i : LONGINT;
  41. BEGIN
  42. IF ~(process.mode IN {Objects.Running,Objects.Ready}) THEN RETURN FALSE END;
  43. i := 0; WHILE (i < oldNofProcesses) & (oldProcesses[i] # process) DO INC(i); END;
  44. RETURN (i >= oldNofProcesses) OR (oldTimes[i] < currentCycles);
  45. END RanMeanwhile;
  46. PROCEDURE Process;
  47. VAR process : Objects.Process; cycles : Objects.CpuCyclesArray; temp : ProcessTimeArray; i : LONGINT;
  48. BEGIN
  49. (*todo: stop gc*)
  50. ProcessInfo.GetProcesses(processes, nofProcesses);
  51. TRACE(nofProcesses);
  52. FOR i := 0 TO nofProcesses - 1 DO
  53. process := processes[i];
  54. Objects.GetCpuCycles(process, cycles, FALSE);
  55. times[i] := cycles[0];
  56. TRACE(process,me,cycles[0],process.mode,Objects.Running);
  57. 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
  58. HandleProcess(process);
  59. END;
  60. END;
  61. temp := oldTimes;
  62. oldTimes := times;
  63. times := temp;
  64. ProcessInfo.Copy(processes, oldProcesses);
  65. oldNofProcesses := nofProcesses;
  66. ProcessInfo.Clear(processes);
  67. (*todo: reenable gc*)
  68. END Process;
  69. BEGIN {ACTIVE, PRIORITY(Objects.Realtime)}
  70. NEW(timer);
  71. me := Objects.CurrentProcess();
  72. TRACE('poller starting');
  73. LOOP
  74. WHILE (state = Running) DO
  75. Process;
  76. timer.Sleep(100);
  77. END;
  78. IF (state = Terminating) THEN EXIT; END;
  79. END;
  80. ProcessInfo.Clear(processes);
  81. ProcessInfo.Clear(oldProcesses);
  82. BEGIN {EXCLUSIVE} state := Terminated; END;
  83. END Poller;
  84. VAR
  85. poller : Poller;
  86. callback : Callback;
  87. state : LONGINT;
  88. PROCEDURE HandleProcess(process : Objects.Process);
  89. (*VAR context : Kernel32.Context; handle : Kernel32.HANDLE; res : Kernel32.BOOL;*)
  90. VAR
  91. threadId: Unix.Thread_t;
  92. stackBottom, sp, bp: ADDRESS;
  93. context: Unix.McontextDesc;
  94. BEGIN
  95. ASSERT(process # NIL);
  96. threadId:=process.threadId;
  97. (*from check at callsite it's guaranteed that the process is running (mode=Objects.Running) *)
  98. (*todo: validate thread ID*)
  99. Unix.ThrSuspend(threadId);
  100. (*because thread suspending is under a mutex in Unix.Mod, this call is guaranteed to have finished with the handler when it returns.*)
  101. context:=process.context;
  102. IF (context.r_pc #0) THEN
  103. stackBottom:=Objects.GetStackBottom(process);
  104. sp:=context.r_sp_x;
  105. bp:=context.r_bp;
  106. IF bp<=stackBottom THEN
  107. callback(1, process, context.r_pc,bp,sp, stackBottom );
  108. ELSE
  109. Unix.ThrResume(threadId);
  110. ASSERT(bp<=stackBottom);
  111. END;
  112. END;
  113. Unix.ThrResume(threadId);
  114. (* handle := process.handle;
  115. IF (handle # Kernel32.NULL) & (handle # Kernel32.InvalidHandleValue) THEN
  116. res := Kernel32.SuspendThread(handle);
  117. IF (res >= 0) THEN
  118. context.ContextFlags := Kernel32.ContextControl+Kernel32.ContextInteger;
  119. res := Kernel32.GetThreadContext(handle, context);
  120. IF (res = Kernel32.True) THEN
  121. IF (context.PC # 0) THEN
  122. stackBottom := Objects.GetStackBottom(process);
  123. bp := context.BP;
  124. sp := context.SP;
  125. ASSERT(context.BP <= stackBottom);
  126. callback(1, process, context.PC, context.BP, context.SP, stackBottom(* LONGINT(0FFFFFFFFH)*) );
  127. END;
  128. END;
  129. res := Kernel32.ResumeThread(handle);
  130. END;
  131. END;
  132. *)
  133. END HandleProcess;
  134. PROCEDURE Enable*(proc : Callback);
  135. BEGIN {EXCLUSIVE}
  136. (*todo: disable gc*)
  137. ASSERT(proc # NIL);
  138. ASSERT((state = Initialized) & (poller = NIL));
  139. callback := proc;
  140. NEW(poller);
  141. state := Running;
  142. END Enable;
  143. PROCEDURE Disable*;
  144. BEGIN {EXCLUSIVE}
  145. (*todo: re-enable gc*)
  146. ASSERT((state = Running) & (poller # NIL));
  147. poller.Terminate;
  148. poller := NIL;
  149. state := Initialized;
  150. END Disable;
  151. PROCEDURE Cleanup;
  152. BEGIN
  153. IF (poller # NIL) THEN poller.Terminate; poller := NIL; END;
  154. END Cleanup;
  155. BEGIN
  156. state := Initialized;
  157. Modules.InstallTermHandler(Cleanup);
  158. END HierarchicalProfiler0.
  159. WMProfiler.Open~
  160. HierarchicalProfiler.Start~
  161. HierarchicalProfiler.Stop~
  162. HierarchicalProfiler.Show~
  163. SystemTools.Free WMProfiler HierarchicalProfiler HierarchicalProfiler0 ~
  164. Test.Busyloop~
  165. Debugging.DisableGC~