typed_macros_internal.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/trace_event/typed_macros_internal.h"
  5. #include "base/notreached.h"
  6. #include "base/time/time.h"
  7. #include "base/trace_event/trace_event.h"
  8. #include "base/trace_event/typed_macros.h"
  9. namespace {
  10. base::ThreadTicks ThreadNow() {
  11. return base::ThreadTicks::IsSupported()
  12. ? base::subtle::ThreadTicksNowIgnoringOverride()
  13. : base::ThreadTicks();
  14. }
  15. base::trace_event::PrepareTrackEventFunction g_typed_event_callback = nullptr;
  16. base::trace_event::PrepareTracePacketFunction g_trace_packet_callback = nullptr;
  17. base::trace_event::EmitEmptyTracePacketFunction g_empty_packet_callback =
  18. nullptr;
  19. std::pair<char /*phase*/, unsigned long long /*id*/>
  20. GetPhaseAndIdForTraceLog(bool explicit_track, uint64_t track_uuid, char phase) {
  21. if (!explicit_track)
  22. return std::make_pair(phase, trace_event_internal::kNoId);
  23. switch (phase) {
  24. case TRACE_EVENT_PHASE_BEGIN:
  25. phase = TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN;
  26. break;
  27. case TRACE_EVENT_PHASE_END:
  28. phase = TRACE_EVENT_PHASE_NESTABLE_ASYNC_END;
  29. break;
  30. case TRACE_EVENT_PHASE_INSTANT:
  31. phase = TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT;
  32. break;
  33. default:
  34. NOTREACHED();
  35. break;
  36. }
  37. return std::make_pair(phase, static_cast<unsigned long long>(track_uuid));
  38. }
  39. } // namespace
  40. namespace trace_event_internal {
  41. const perfetto::Track kDefaultTrack{};
  42. } // namespace trace_event_internal
  43. namespace base {
  44. namespace trace_event {
  45. void EnableTypedTraceEvents(
  46. PrepareTrackEventFunction typed_event_callback,
  47. PrepareTracePacketFunction trace_packet_callback,
  48. EmitEmptyTracePacketFunction empty_packet_callback) {
  49. g_typed_event_callback = typed_event_callback;
  50. g_trace_packet_callback = trace_packet_callback;
  51. g_empty_packet_callback = empty_packet_callback;
  52. }
  53. void ResetTypedTraceEventsForTesting() {
  54. g_typed_event_callback = nullptr;
  55. g_trace_packet_callback = nullptr;
  56. g_empty_packet_callback = nullptr;
  57. }
  58. TrackEventHandle::TrackEventHandle(TrackEvent* event,
  59. IncrementalState* incremental_state,
  60. CompletionListener* listener)
  61. : event_(event),
  62. incremental_state_(incremental_state),
  63. listener_(listener) {}
  64. TrackEventHandle::TrackEventHandle()
  65. : TrackEventHandle(nullptr, nullptr, nullptr) {}
  66. TrackEventHandle::~TrackEventHandle() {
  67. if (listener_)
  68. listener_->OnTrackEventCompleted();
  69. }
  70. TrackEventHandle::CompletionListener::~CompletionListener() = default;
  71. TracePacketHandle::TracePacketHandle(PerfettoPacketHandle packet,
  72. CompletionListener* listener)
  73. : packet_(std::move(packet)), listener_(listener) {}
  74. TracePacketHandle::TracePacketHandle()
  75. : TracePacketHandle(PerfettoPacketHandle(), nullptr) {}
  76. TracePacketHandle::~TracePacketHandle() {
  77. if (listener_)
  78. listener_->OnTracePacketCompleted();
  79. }
  80. TracePacketHandle::TracePacketHandle(TracePacketHandle&& handle) noexcept {
  81. *this = std::move(handle);
  82. }
  83. TracePacketHandle& TracePacketHandle::operator=(TracePacketHandle&& handle) {
  84. this->packet_ = std::move(handle.packet_);
  85. this->listener_ = handle.listener_;
  86. return *this;
  87. }
  88. TracePacketHandle::CompletionListener::~CompletionListener() = default;
  89. } // namespace trace_event
  90. } // namespace base
  91. namespace trace_event_internal {
  92. base::trace_event::TrackEventHandle CreateTrackEvent(
  93. char phase,
  94. const unsigned char* category_group_enabled,
  95. perfetto::StaticString name,
  96. base::TimeTicks ts,
  97. uint64_t track_uuid,
  98. bool explicit_track) {
  99. DCHECK(phase == TRACE_EVENT_PHASE_BEGIN || phase == TRACE_EVENT_PHASE_END ||
  100. phase == TRACE_EVENT_PHASE_INSTANT);
  101. DCHECK(category_group_enabled);
  102. if (!g_typed_event_callback)
  103. return base::trace_event::TrackEventHandle();
  104. const auto thread_id = base::PlatformThread::CurrentId();
  105. auto* trace_log = base::trace_event::TraceLog::GetInstance();
  106. DCHECK(trace_log);
  107. // Provide events emitted onto different tracks as NESTABLE_ASYNC events to
  108. // TraceLog, so that e.g. ETW export is aware of them not being a sync event
  109. // for the current thread.
  110. auto phase_and_id_for_trace_log =
  111. GetPhaseAndIdForTraceLog(explicit_track, track_uuid, phase);
  112. if (!trace_log->ShouldAddAfterUpdatingState(
  113. phase_and_id_for_trace_log.first, category_group_enabled, name.value,
  114. phase_and_id_for_trace_log.second, thread_id, nullptr)) {
  115. return base::trace_event::TrackEventHandle();
  116. }
  117. unsigned int flags = TRACE_EVENT_FLAG_NONE;
  118. if (ts.is_null()) {
  119. ts = TRACE_TIME_TICKS_NOW();
  120. } else {
  121. flags |= TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP;
  122. }
  123. if (phase == TRACE_EVENT_PHASE_INSTANT && !explicit_track) {
  124. flags |= TRACE_EVENT_SCOPE_THREAD;
  125. }
  126. // Only emit thread time / instruction count for events on the default track
  127. // without explicit timestamp.
  128. base::ThreadTicks thread_now;
  129. if ((flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP) == 0 && !explicit_track) {
  130. thread_now = ThreadNow();
  131. }
  132. base::trace_event::TraceEvent event(
  133. thread_id, ts, thread_now, phase, category_group_enabled, name.value,
  134. trace_event_internal::kGlobalScope, trace_event_internal::kNoId,
  135. trace_event_internal::kNoId, nullptr, flags);
  136. return g_typed_event_callback(&event);
  137. }
  138. base::trace_event::TracePacketHandle CreateTracePacket() {
  139. // We only call CreateTracePacket() if the embedder installed a valid
  140. // g_typed_event_callback, and in that case we also expect a valid
  141. // g_trace_packet_callback.
  142. DCHECK(g_trace_packet_callback);
  143. return g_trace_packet_callback();
  144. }
  145. void AddEmptyPacket() {
  146. if (g_empty_packet_callback)
  147. g_empty_packet_callback();
  148. }
  149. bool ShouldEmitTrackDescriptor(
  150. uint64_t track_uuid,
  151. base::trace_event::TrackEventHandle::IncrementalState* incr_state) {
  152. auto it_and_inserted = incr_state->seen_tracks.insert(track_uuid);
  153. return it_and_inserted.second;
  154. }
  155. } // namespace trace_event_internal