0

For a simple sampling profiler I'm suspending a target thread, get its current stacktrace, then continue it. Now I would like to highlight a sample differently if the thread was in a waiting state.

So I want to know if the thread was blocking (waiting via WaitForSingleObject, pausing via Sleep, ...) at the time it was suspended.

I can get this information via NtQuerySystemInformation(SystemProcessInformation), but that gets much more than needed, the information of each thread of each process.

Also I saw Performance Counters, but I'm not sure if it's possible with this API, if I only have the thread ID/handle.

UPDATE: IInspectable gave me a hint with Wait Chain Traversal, while it seemed a good fit, it gives back the status ObjectStatus==WctStatusBlocked for all suspended threads, which isn't unreasonable, but doesn't work for my problem. It is also very slow, I assume because it collects the data for the whole chain, while I only care for the first element.

ssbssa
  • 1,261
  • 1
  • 13
  • 21
  • *"but that gets much more than needed"* - Is that a problem? – klutt Sep 09 '18 at 03:21
  • Possible duplicate of [Check if a Win32 thread is running or in a suspended state](https://stackoverflow.com/questions/1006691/check-if-a-win32-thread-is-running-or-in-a-suspended-state) – mnistic Sep 09 '18 at 03:44
  • Do you mean suspended or merely blocked? Oh, you want to know if it was blocked before you suspended it... – Ben Voigt Sep 09 '18 at 05:08
  • @mnistic: Definitely not a duplicate. OP knows the thread is suspended, because he suspended it. – Ben Voigt Sep 09 '18 at 05:11
  • 1
    [Wait Chain Traversal](https://learn.microsoft.com/en-us/windows/desktop/debug/wait-chain-traversal) may get you that information. – IInspectable Sep 09 '18 at 06:44
  • @Broman Yes, this is done periodically, so it would slow down the process a lot. – ssbssa Sep 09 '18 at 11:11
  • @IInspectable Sadly, `GetThreadWaitChain` always says a thread has `ObjectStatus==WctStatusBlocked` if it is suspended, otherwise this would have been perfect. – ssbssa Sep 09 '18 at 14:15
  • Hmm, a sampling profiler needs to walk the stack. A stack that has a wait function on it just isn't very special, there are only a small subset of native functions. Do this at display-time instead of sampling-time, human eyes are not that fast. – Hans Passant Sep 09 '18 at 16:14
  • @HansPassant That was actually my first idea as well, but this isn't always reliable. For example when doing a `_getch()` I have `ZwRequestWaitReplyPort` in the top level for 64bit, but on 32bit it's `DuplicateConsoleHandle` for some reason. But maybe that still is the best solution anyways. – ssbssa Sep 09 '18 at 17:18

1 Answers1

0

While not exactly what I wanted, QueryThreadCycleTime is close enough.

So each time the thread is suspended, QueryThreadCycleTime is called, which returns the number of CPU clock cycles used by this thread up to this point. If the difference to the previous call is below a certain limit, the current sample is then considered as waiting.

It's not perfect, the first sample taken while the thread entered a waiting state is not detected as waiting, and the limit might not work for all CPUs the same.

ssbssa
  • 1,261
  • 1
  • 13
  • 21