11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include <stdio.h> 61cb0ef41Sopenharmony_ci#include <stdlib.h> 71cb0ef41Sopenharmony_ci#include <string.h> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "include/libplatform/v8-tracing.h" 101cb0ef41Sopenharmony_ci#include "src/base/atomicops.h" 111cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h" 121cb0ef41Sopenharmony_ci#include "src/base/platform/time.h" 131cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci#ifdef V8_USE_PERFETTO 161cb0ef41Sopenharmony_ci#include "perfetto/ext/trace_processor/export_json.h" 171cb0ef41Sopenharmony_ci#include "perfetto/trace_processor/trace_processor.h" 181cb0ef41Sopenharmony_ci#include "perfetto/tracing/tracing.h" 191cb0ef41Sopenharmony_ci#include "protos/perfetto/config/data_source_config.gen.h" 201cb0ef41Sopenharmony_ci#include "protos/perfetto/config/trace_config.gen.h" 211cb0ef41Sopenharmony_ci#include "protos/perfetto/config/track_event/track_event_config.gen.h" 221cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h" 231cb0ef41Sopenharmony_ci#include "src/base/platform/semaphore.h" 241cb0ef41Sopenharmony_ci#include "src/libplatform/tracing/trace-event-listener.h" 251cb0ef41Sopenharmony_ci#endif // V8_USE_PERFETTO 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci#ifdef V8_USE_PERFETTO 281cb0ef41Sopenharmony_ciclass JsonOutputWriter : public perfetto::trace_processor::json::OutputWriter { 291cb0ef41Sopenharmony_ci public: 301cb0ef41Sopenharmony_ci explicit JsonOutputWriter(std::ostream* stream) : stream_(stream) {} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci perfetto::trace_processor::util::Status AppendString( 331cb0ef41Sopenharmony_ci const std::string& string) override { 341cb0ef41Sopenharmony_ci *stream_ << string; 351cb0ef41Sopenharmony_ci return perfetto::trace_processor::util::OkStatus(); 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci private: 391cb0ef41Sopenharmony_ci std::ostream* stream_; 401cb0ef41Sopenharmony_ci}; 411cb0ef41Sopenharmony_ci#endif // V8_USE_PERFETTO 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cinamespace v8 { 441cb0ef41Sopenharmony_cinamespace platform { 451cb0ef41Sopenharmony_cinamespace tracing { 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci#if !defined(V8_USE_PERFETTO) 481cb0ef41Sopenharmony_cistatic const size_t kMaxCategoryGroups = 200; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci// Parallel arrays g_category_groups and g_category_group_enabled are separate 511cb0ef41Sopenharmony_ci// so that a pointer to a member of g_category_group_enabled can be easily 521cb0ef41Sopenharmony_ci// converted to an index into g_category_groups. This allows macros to deal 531cb0ef41Sopenharmony_ci// only with char enabled pointers from g_category_group_enabled, and we can 541cb0ef41Sopenharmony_ci// convert internally to determine the category name from the char enabled 551cb0ef41Sopenharmony_ci// pointer. 561cb0ef41Sopenharmony_ciconst char* g_category_groups[kMaxCategoryGroups] = { 571cb0ef41Sopenharmony_ci "toplevel", 581cb0ef41Sopenharmony_ci "tracing categories exhausted; must increase kMaxCategoryGroups", 591cb0ef41Sopenharmony_ci "__metadata"}; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci// The enabled flag is char instead of bool so that the API can be used from C. 621cb0ef41Sopenharmony_ciunsigned char g_category_group_enabled[kMaxCategoryGroups] = {0}; 631cb0ef41Sopenharmony_ci// Indexes here have to match the g_category_groups array indexes above. 641cb0ef41Sopenharmony_ciconst int g_category_categories_exhausted = 1; 651cb0ef41Sopenharmony_ci// Metadata category not used in V8. 661cb0ef41Sopenharmony_ci// const int g_category_metadata = 2; 671cb0ef41Sopenharmony_ciconst int g_num_builtin_categories = 3; 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci// Skip default categories. 701cb0ef41Sopenharmony_civ8::base::AtomicWord g_category_index = g_num_builtin_categories; 711cb0ef41Sopenharmony_ci#endif // !defined(V8_USE_PERFETTO) 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ciTracingController::TracingController() { mutex_.reset(new base::Mutex()); } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ciTracingController::~TracingController() { 761cb0ef41Sopenharmony_ci StopTracing(); 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci#if !defined(V8_USE_PERFETTO) 791cb0ef41Sopenharmony_ci { 801cb0ef41Sopenharmony_ci // Free memory for category group names allocated via strdup. 811cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 821cb0ef41Sopenharmony_ci for (size_t i = g_category_index - 1; i >= g_num_builtin_categories; --i) { 831cb0ef41Sopenharmony_ci const char* group = g_category_groups[i]; 841cb0ef41Sopenharmony_ci g_category_groups[i] = nullptr; 851cb0ef41Sopenharmony_ci free(const_cast<char*>(group)); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci g_category_index = g_num_builtin_categories; 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci#endif // !defined(V8_USE_PERFETTO) 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci#ifdef V8_USE_PERFETTO 931cb0ef41Sopenharmony_civoid TracingController::InitializeForPerfetto(std::ostream* output_stream) { 941cb0ef41Sopenharmony_ci output_stream_ = output_stream; 951cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(output_stream); 961cb0ef41Sopenharmony_ci DCHECK(output_stream->good()); 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_civoid TracingController::SetTraceEventListenerForTesting( 1001cb0ef41Sopenharmony_ci TraceEventListener* listener) { 1011cb0ef41Sopenharmony_ci listener_for_testing_ = listener; 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ci#else // !V8_USE_PERFETTO 1041cb0ef41Sopenharmony_civoid TracingController::Initialize(TraceBuffer* trace_buffer) { 1051cb0ef41Sopenharmony_ci trace_buffer_.reset(trace_buffer); 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ciint64_t TracingController::CurrentTimestampMicroseconds() { 1091cb0ef41Sopenharmony_ci return base::TimeTicks::Now().ToInternalValue(); 1101cb0ef41Sopenharmony_ci} 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ciint64_t TracingController::CurrentCpuTimestampMicroseconds() { 1131cb0ef41Sopenharmony_ci return base::ThreadTicks::Now().ToInternalValue(); 1141cb0ef41Sopenharmony_ci} 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ciuint64_t TracingController::AddTraceEvent( 1171cb0ef41Sopenharmony_ci char phase, const uint8_t* category_enabled_flag, const char* name, 1181cb0ef41Sopenharmony_ci const char* scope, uint64_t id, uint64_t bind_id, int num_args, 1191cb0ef41Sopenharmony_ci const char** arg_names, const uint8_t* arg_types, 1201cb0ef41Sopenharmony_ci const uint64_t* arg_values, 1211cb0ef41Sopenharmony_ci std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 1221cb0ef41Sopenharmony_ci unsigned int flags) { 1231cb0ef41Sopenharmony_ci int64_t now_us = CurrentTimestampMicroseconds(); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci return AddTraceEventWithTimestamp( 1261cb0ef41Sopenharmony_ci phase, category_enabled_flag, name, scope, id, bind_id, num_args, 1271cb0ef41Sopenharmony_ci arg_names, arg_types, arg_values, arg_convertables, flags, now_us); 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ciuint64_t TracingController::AddTraceEventWithTimestamp( 1311cb0ef41Sopenharmony_ci char phase, const uint8_t* category_enabled_flag, const char* name, 1321cb0ef41Sopenharmony_ci const char* scope, uint64_t id, uint64_t bind_id, int num_args, 1331cb0ef41Sopenharmony_ci const char** arg_names, const uint8_t* arg_types, 1341cb0ef41Sopenharmony_ci const uint64_t* arg_values, 1351cb0ef41Sopenharmony_ci std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 1361cb0ef41Sopenharmony_ci unsigned int flags, int64_t timestamp) { 1371cb0ef41Sopenharmony_ci int64_t cpu_now_us = CurrentCpuTimestampMicroseconds(); 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci uint64_t handle = 0; 1401cb0ef41Sopenharmony_ci if (recording_.load(std::memory_order_acquire)) { 1411cb0ef41Sopenharmony_ci TraceObject* trace_object = trace_buffer_->AddTraceEvent(&handle); 1421cb0ef41Sopenharmony_ci if (trace_object) { 1431cb0ef41Sopenharmony_ci { 1441cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 1451cb0ef41Sopenharmony_ci trace_object->Initialize(phase, category_enabled_flag, name, scope, id, 1461cb0ef41Sopenharmony_ci bind_id, num_args, arg_names, arg_types, 1471cb0ef41Sopenharmony_ci arg_values, arg_convertables, flags, timestamp, 1481cb0ef41Sopenharmony_ci cpu_now_us); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci return handle; 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_civoid TracingController::UpdateTraceEventDuration( 1561cb0ef41Sopenharmony_ci const uint8_t* category_enabled_flag, const char* name, uint64_t handle) { 1571cb0ef41Sopenharmony_ci int64_t now_us = CurrentTimestampMicroseconds(); 1581cb0ef41Sopenharmony_ci int64_t cpu_now_us = CurrentCpuTimestampMicroseconds(); 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci TraceObject* trace_object = trace_buffer_->GetEventByHandle(handle); 1611cb0ef41Sopenharmony_ci if (!trace_object) return; 1621cb0ef41Sopenharmony_ci trace_object->UpdateDuration(now_us, cpu_now_us); 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ciconst char* TracingController::GetCategoryGroupName( 1661cb0ef41Sopenharmony_ci const uint8_t* category_group_enabled) { 1671cb0ef41Sopenharmony_ci // Calculate the index of the category group by finding 1681cb0ef41Sopenharmony_ci // category_group_enabled in g_category_group_enabled array. 1691cb0ef41Sopenharmony_ci uintptr_t category_begin = 1701cb0ef41Sopenharmony_ci reinterpret_cast<uintptr_t>(g_category_group_enabled); 1711cb0ef41Sopenharmony_ci uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled); 1721cb0ef41Sopenharmony_ci // Check for out of bounds category pointers. 1731cb0ef41Sopenharmony_ci DCHECK(category_ptr >= category_begin && 1741cb0ef41Sopenharmony_ci category_ptr < reinterpret_cast<uintptr_t>(g_category_group_enabled + 1751cb0ef41Sopenharmony_ci kMaxCategoryGroups)); 1761cb0ef41Sopenharmony_ci uintptr_t category_index = 1771cb0ef41Sopenharmony_ci (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); 1781cb0ef41Sopenharmony_ci return g_category_groups[category_index]; 1791cb0ef41Sopenharmony_ci} 1801cb0ef41Sopenharmony_ci#endif // !defined(V8_USE_PERFETTO) 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_civoid TracingController::StartTracing(TraceConfig* trace_config) { 1831cb0ef41Sopenharmony_ci#ifdef V8_USE_PERFETTO 1841cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(output_stream_); 1851cb0ef41Sopenharmony_ci DCHECK(output_stream_->good()); 1861cb0ef41Sopenharmony_ci perfetto::trace_processor::Config processor_config; 1871cb0ef41Sopenharmony_ci trace_processor_ = 1881cb0ef41Sopenharmony_ci perfetto::trace_processor::TraceProcessorStorage::CreateInstance( 1891cb0ef41Sopenharmony_ci processor_config); 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci ::perfetto::TraceConfig perfetto_trace_config; 1921cb0ef41Sopenharmony_ci perfetto_trace_config.add_buffers()->set_size_kb(4096); 1931cb0ef41Sopenharmony_ci auto ds_config = perfetto_trace_config.add_data_sources()->mutable_config(); 1941cb0ef41Sopenharmony_ci ds_config->set_name("track_event"); 1951cb0ef41Sopenharmony_ci perfetto::protos::gen::TrackEventConfig te_config; 1961cb0ef41Sopenharmony_ci te_config.add_disabled_categories("*"); 1971cb0ef41Sopenharmony_ci for (const auto& category : trace_config->GetEnabledCategories()) 1981cb0ef41Sopenharmony_ci te_config.add_enabled_categories(category); 1991cb0ef41Sopenharmony_ci ds_config->set_track_event_config_raw(te_config.SerializeAsString()); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci tracing_session_ = 2021cb0ef41Sopenharmony_ci perfetto::Tracing::NewTrace(perfetto::BackendType::kUnspecifiedBackend); 2031cb0ef41Sopenharmony_ci tracing_session_->Setup(perfetto_trace_config); 2041cb0ef41Sopenharmony_ci tracing_session_->StartBlocking(); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci#endif // V8_USE_PERFETTO 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci trace_config_.reset(trace_config); 2091cb0ef41Sopenharmony_ci std::unordered_set<v8::TracingController::TraceStateObserver*> observers_copy; 2101cb0ef41Sopenharmony_ci { 2111cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 2121cb0ef41Sopenharmony_ci recording_.store(true, std::memory_order_release); 2131cb0ef41Sopenharmony_ci#ifndef V8_USE_PERFETTO 2141cb0ef41Sopenharmony_ci UpdateCategoryGroupEnabledFlags(); 2151cb0ef41Sopenharmony_ci#endif 2161cb0ef41Sopenharmony_ci observers_copy = observers_; 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci for (auto o : observers_copy) { 2191cb0ef41Sopenharmony_ci o->OnTraceEnabled(); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci} 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_civoid TracingController::StopTracing() { 2241cb0ef41Sopenharmony_ci bool expected = true; 2251cb0ef41Sopenharmony_ci if (!recording_.compare_exchange_strong(expected, false)) { 2261cb0ef41Sopenharmony_ci return; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci#ifndef V8_USE_PERFETTO 2291cb0ef41Sopenharmony_ci UpdateCategoryGroupEnabledFlags(); 2301cb0ef41Sopenharmony_ci#endif 2311cb0ef41Sopenharmony_ci std::unordered_set<v8::TracingController::TraceStateObserver*> observers_copy; 2321cb0ef41Sopenharmony_ci { 2331cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 2341cb0ef41Sopenharmony_ci observers_copy = observers_; 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci for (auto o : observers_copy) { 2371cb0ef41Sopenharmony_ci o->OnTraceDisabled(); 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci#ifdef V8_USE_PERFETTO 2411cb0ef41Sopenharmony_ci tracing_session_->StopBlocking(); 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci std::vector<char> trace = tracing_session_->ReadTraceBlocking(); 2441cb0ef41Sopenharmony_ci std::unique_ptr<uint8_t[]> trace_bytes(new uint8_t[trace.size()]); 2451cb0ef41Sopenharmony_ci std::copy(&trace[0], &trace[0] + trace.size(), &trace_bytes[0]); 2461cb0ef41Sopenharmony_ci trace_processor_->Parse(std::move(trace_bytes), trace.size()); 2471cb0ef41Sopenharmony_ci trace_processor_->NotifyEndOfFile(); 2481cb0ef41Sopenharmony_ci JsonOutputWriter output_writer(output_stream_); 2491cb0ef41Sopenharmony_ci auto status = perfetto::trace_processor::json::ExportJson( 2501cb0ef41Sopenharmony_ci trace_processor_.get(), &output_writer, nullptr, nullptr, nullptr); 2511cb0ef41Sopenharmony_ci DCHECK(status.ok()); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci if (listener_for_testing_) listener_for_testing_->ParseFromArray(trace); 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci trace_processor_.reset(); 2561cb0ef41Sopenharmony_ci#else 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci { 2591cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 2601cb0ef41Sopenharmony_ci DCHECK(trace_buffer_); 2611cb0ef41Sopenharmony_ci trace_buffer_->Flush(); 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci#endif // V8_USE_PERFETTO 2641cb0ef41Sopenharmony_ci} 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci#if !defined(V8_USE_PERFETTO) 2671cb0ef41Sopenharmony_civoid TracingController::UpdateCategoryGroupEnabledFlag(size_t category_index) { 2681cb0ef41Sopenharmony_ci unsigned char enabled_flag = 0; 2691cb0ef41Sopenharmony_ci const char* category_group = g_category_groups[category_index]; 2701cb0ef41Sopenharmony_ci if (recording_.load(std::memory_order_acquire) && 2711cb0ef41Sopenharmony_ci trace_config_->IsCategoryGroupEnabled(category_group)) { 2721cb0ef41Sopenharmony_ci enabled_flag |= ENABLED_FOR_RECORDING; 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci // TODO(fmeawad): EventCallback and ETW modes are not yet supported in V8. 2761cb0ef41Sopenharmony_ci // TODO(primiano): this is a temporary workaround for catapult:#2341, 2771cb0ef41Sopenharmony_ci // to guarantee that metadata events are always added even if the category 2781cb0ef41Sopenharmony_ci // filter is "-*". See crbug.com/618054 for more details and long-term fix. 2791cb0ef41Sopenharmony_ci if (recording_.load(std::memory_order_acquire) && 2801cb0ef41Sopenharmony_ci !strcmp(category_group, "__metadata")) { 2811cb0ef41Sopenharmony_ci enabled_flag |= ENABLED_FOR_RECORDING; 2821cb0ef41Sopenharmony_ci } 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci base::Relaxed_Store(reinterpret_cast<base::Atomic8*>( 2851cb0ef41Sopenharmony_ci g_category_group_enabled + category_index), 2861cb0ef41Sopenharmony_ci enabled_flag); 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_civoid TracingController::UpdateCategoryGroupEnabledFlags() { 2901cb0ef41Sopenharmony_ci size_t category_index = base::Acquire_Load(&g_category_index); 2911cb0ef41Sopenharmony_ci for (size_t i = 0; i < category_index; i++) UpdateCategoryGroupEnabledFlag(i); 2921cb0ef41Sopenharmony_ci} 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ciconst uint8_t* TracingController::GetCategoryGroupEnabled( 2951cb0ef41Sopenharmony_ci const char* category_group) { 2961cb0ef41Sopenharmony_ci // Check that category group does not contain double quote 2971cb0ef41Sopenharmony_ci DCHECK(!strchr(category_group, '"')); 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci // The g_category_groups is append only, avoid using a lock for the fast path. 3001cb0ef41Sopenharmony_ci size_t category_index = base::Acquire_Load(&g_category_index); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci // Search for pre-existing category group. 3031cb0ef41Sopenharmony_ci for (size_t i = 0; i < category_index; ++i) { 3041cb0ef41Sopenharmony_ci if (strcmp(g_category_groups[i], category_group) == 0) { 3051cb0ef41Sopenharmony_ci return &g_category_group_enabled[i]; 3061cb0ef41Sopenharmony_ci } 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci // Slow path. Grab the lock. 3101cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci // Check the list again with lock in hand. 3131cb0ef41Sopenharmony_ci unsigned char* category_group_enabled = nullptr; 3141cb0ef41Sopenharmony_ci category_index = base::Acquire_Load(&g_category_index); 3151cb0ef41Sopenharmony_ci for (size_t i = 0; i < category_index; ++i) { 3161cb0ef41Sopenharmony_ci if (strcmp(g_category_groups[i], category_group) == 0) { 3171cb0ef41Sopenharmony_ci return &g_category_group_enabled[i]; 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci // Create a new category group. 3221cb0ef41Sopenharmony_ci // Check that there is a slot for the new category_group. 3231cb0ef41Sopenharmony_ci DCHECK(category_index < kMaxCategoryGroups); 3241cb0ef41Sopenharmony_ci if (category_index < kMaxCategoryGroups) { 3251cb0ef41Sopenharmony_ci // Don't hold on to the category_group pointer, so that we can create 3261cb0ef41Sopenharmony_ci // category groups with strings not known at compile time (this is 3271cb0ef41Sopenharmony_ci // required by SetWatchEvent). 3281cb0ef41Sopenharmony_ci const char* new_group = base::Strdup(category_group); 3291cb0ef41Sopenharmony_ci g_category_groups[category_index] = new_group; 3301cb0ef41Sopenharmony_ci DCHECK(!g_category_group_enabled[category_index]); 3311cb0ef41Sopenharmony_ci // Note that if both included and excluded patterns in the 3321cb0ef41Sopenharmony_ci // TraceConfig are empty, we exclude nothing, 3331cb0ef41Sopenharmony_ci // thereby enabling this category group. 3341cb0ef41Sopenharmony_ci UpdateCategoryGroupEnabledFlag(category_index); 3351cb0ef41Sopenharmony_ci category_group_enabled = &g_category_group_enabled[category_index]; 3361cb0ef41Sopenharmony_ci // Update the max index now. 3371cb0ef41Sopenharmony_ci base::Release_Store(&g_category_index, category_index + 1); 3381cb0ef41Sopenharmony_ci } else { 3391cb0ef41Sopenharmony_ci category_group_enabled = 3401cb0ef41Sopenharmony_ci &g_category_group_enabled[g_category_categories_exhausted]; 3411cb0ef41Sopenharmony_ci } 3421cb0ef41Sopenharmony_ci return category_group_enabled; 3431cb0ef41Sopenharmony_ci} 3441cb0ef41Sopenharmony_ci#endif // !defined(V8_USE_PERFETTO) 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_civoid TracingController::AddTraceStateObserver( 3471cb0ef41Sopenharmony_ci v8::TracingController::TraceStateObserver* observer) { 3481cb0ef41Sopenharmony_ci { 3491cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 3501cb0ef41Sopenharmony_ci observers_.insert(observer); 3511cb0ef41Sopenharmony_ci if (!recording_.load(std::memory_order_acquire)) return; 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci // Fire the observer if recording is already in progress. 3541cb0ef41Sopenharmony_ci observer->OnTraceEnabled(); 3551cb0ef41Sopenharmony_ci} 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_civoid TracingController::RemoveTraceStateObserver( 3581cb0ef41Sopenharmony_ci v8::TracingController::TraceStateObserver* observer) { 3591cb0ef41Sopenharmony_ci base::MutexGuard lock(mutex_.get()); 3601cb0ef41Sopenharmony_ci DCHECK(observers_.find(observer) != observers_.end()); 3611cb0ef41Sopenharmony_ci observers_.erase(observer); 3621cb0ef41Sopenharmony_ci} 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci} // namespace tracing 3651cb0ef41Sopenharmony_ci} // namespace platform 3661cb0ef41Sopenharmony_ci} // namespace v8 367