callstack.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include "callstack.h"
  2. #include <util/thread/singleton.h>
  3. #ifdef USE_ACTOR_CALLSTACK
  4. namespace NActors {
  5. namespace {
  6. void (*PreviousFormatBackTrace)(IOutputStream*) = 0;
  7. ui32 ActorBackTraceEnableCounter = 0;
  8. }
  9. void ActorFormatBackTrace(IOutputStream* out) {
  10. TStringStream str;
  11. PreviousFormatBackTrace(&str);
  12. str << Endl;
  13. TCallstack::DumpCallstack(str);
  14. *out << str.Str();
  15. }
  16. void EnableActorCallstack() {
  17. if (ActorBackTraceEnableCounter == 0) {
  18. Y_ABORT_UNLESS(PreviousFormatBackTrace == 0);
  19. PreviousFormatBackTrace = SetFormatBackTraceFn(ActorFormatBackTrace);
  20. }
  21. ++ActorBackTraceEnableCounter;
  22. }
  23. void DisableActorCallstack() {
  24. --ActorBackTraceEnableCounter;
  25. if (ActorBackTraceEnableCounter == 0) {
  26. Y_ABORT_UNLESS(PreviousFormatBackTrace);
  27. SetFormatBackTraceFn(PreviousFormatBackTrace);
  28. PreviousFormatBackTrace = 0;
  29. }
  30. }
  31. TCallstack::TCallstack()
  32. : BeginIdx(0)
  33. , Size(0)
  34. , LinesToSkip(0)
  35. {
  36. }
  37. void TCallstack::SetLinesToSkip() {
  38. TTrace record;
  39. LinesToSkip = BackTrace(record.Data, TTrace::CAPACITY);
  40. }
  41. void TCallstack::Trace() {
  42. size_t currentIdx = (BeginIdx + Size) % RECORDS;
  43. if (Size == RECORDS) {
  44. ++BeginIdx;
  45. } else {
  46. ++Size;
  47. }
  48. TTrace& record = Record[currentIdx];
  49. record.Size = BackTrace(record.Data, TTrace::CAPACITY);
  50. record.LinesToSkip = LinesToSkip;
  51. }
  52. void TCallstack::TraceIfEmpty() {
  53. if (Size == 0) {
  54. LinesToSkip = 0;
  55. Trace();
  56. }
  57. }
  58. TCallstack& TCallstack::GetTlsCallstack() {
  59. return *FastTlsSingleton<TCallstack>();
  60. }
  61. void TCallstack::DumpCallstack(TStringStream& str) {
  62. TCallstack& callstack = GetTlsCallstack();
  63. for (int i = callstack.Size - 1; i >= 0; --i) {
  64. TTrace& record = callstack.Record[(callstack.BeginIdx + i) % RECORDS];
  65. str << Endl << "Trace entry " << i << Endl << Endl;
  66. size_t size = record.Size;
  67. if (size > record.LinesToSkip && size < TTrace::CAPACITY) {
  68. size -= record.LinesToSkip;
  69. }
  70. if (size > RECORDS_TO_SKIP) {
  71. FormatBackTrace(&str, &record.Data[RECORDS_TO_SKIP], size - RECORDS_TO_SKIP);
  72. } else {
  73. FormatBackTrace(&str, record.Data, size);
  74. }
  75. str << Endl;
  76. }
  77. }
  78. }
  79. #endif