Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: base/debug/trace_event_impl.cc

Issue 10837082: implement SetWatchEvent and WaitForEvent for trace-based-tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sky, piman feedback Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event_impl.h" 5 #include "base/debug/trace_event_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/leak_annotations.h"
10 #include "base/debug/trace_event.h" 11 #include "base/debug/trace_event.h"
11 #include "base/file_util.h" 12 #include "base/file_util.h"
12 #include "base/format_macros.h" 13 #include "base/format_macros.h"
13 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
14 #include "base/memory/singleton.h" 15 #include "base/memory/singleton.h"
15 #include "base/process_util.h" 16 #include "base/process_util.h"
17 #include "base/stl_util.h"
16 #include "base/stringprintf.h" 18 #include "base/stringprintf.h"
17 #include "base/string_tokenizer.h" 19 #include "base/string_tokenizer.h"
20 #include "base/string_util.h"
21 #include "base/sys_info.h"
22 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
18 #include "base/threading/platform_thread.h" 23 #include "base/threading/platform_thread.h"
19 #include "base/threading/thread_local.h" 24 #include "base/threading/thread_local.h"
25 #include "base/time.h"
20 #include "base/utf_string_conversions.h" 26 #include "base/utf_string_conversions.h"
21 #include "base/stl_util.h"
22 #include "base/sys_info.h"
23 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
24 #include "base/time.h"
25 27
26 #if defined(OS_WIN) 28 #if defined(OS_WIN)
27 #include "base/debug/trace_event_win.h" 29 #include "base/debug/trace_event_win.h"
28 #endif 30 #endif
29 31
30 class DeleteTraceLogForTesting { 32 class DeleteTraceLogForTesting {
31 public: 33 public:
32 static void Delete() { 34 static void Delete() {
33 Singleton<base::debug::TraceLog, 35 Singleton<base::debug::TraceLog,
34 StaticMemorySingletonTraits<base::debug::TraceLog> >::OnExit(0); 36 StaticMemorySingletonTraits<base::debug::TraceLog> >::OnExit(0);
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 void TraceResultBuffer::Finish() { 311 void TraceResultBuffer::Finish() {
310 output_callback_.Run("]"); 312 output_callback_.Run("]");
311 } 313 }
312 314
313 //////////////////////////////////////////////////////////////////////////////// 315 ////////////////////////////////////////////////////////////////////////////////
314 // 316 //
315 // TraceLog 317 // TraceLog
316 // 318 //
317 //////////////////////////////////////////////////////////////////////////////// 319 ////////////////////////////////////////////////////////////////////////////////
318 320
321 TraceLog::NotificationHelper::NotificationHelper(TraceLog* trace_log)
322 : trace_log_(trace_log)
323 , notification_(0) {
jar (doing other things) 2012/08/29 22:38:19 nit: comma on end of previous line.
jbates 2012/08/29 23:12:06 Done.
324 }
325
326 TraceLog::NotificationHelper::~NotificationHelper() {
327 }
328
329 void TraceLog::NotificationHelper::AddNotificationWhileLocked(
330 int notification) {
331 if (trace_log_->notification_callback_.is_null())
332 return;
333 if (notification_ == 0) {
334 callback_copy_ = trace_log_->notification_callback_;
335 ++trace_log_->notification_thread_count_;
336 }
337 notification_ |= notification;
338 }
339
340 void TraceLog::NotificationHelper::SendNotificationIfAny() {
341 if (notification_) {
jar (doing other things) 2012/08/29 22:38:19 nit: early return would mean you don't need to ind
jbates 2012/08/29 23:12:06 Done.
342 callback_copy_.Run(notification_);
343 callback_copy_.Reset();
344
345 AutoLock lock(trace_log_->lock_);
346 --trace_log_->notification_thread_count_;
347 // Signal other waiters (if any) in case they are waiting for the
348 // callback object to be unreferenced.
349 if (trace_log_->notification_thread_count_ == 0)
350 trace_log_->notification_condition_.Signal();
351 }
352 }
353
319 // static 354 // static
320 TraceLog* TraceLog::GetInstance() { 355 TraceLog* TraceLog::GetInstance() {
321 return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get(); 356 return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get();
322 } 357 }
323 358
324 TraceLog::TraceLog() 359 TraceLog::TraceLog()
325 : enabled_(false) 360 : enabled_(false)
326 , dispatching_to_observer_list_(false) { 361 , notification_condition_(&lock_)
jar (doing other things) 2012/08/29 22:38:19 nit: comma on end of lines (...though this was a
jbates 2012/08/29 23:12:06 Done. Oops, I must have been infected by WebKit st
362 , notification_thread_count_(0)
363 , dispatching_to_observer_list_(false)
364 , watch_category_(NULL) {
327 // Trace is enabled or disabled on one thread while other threads are 365 // Trace is enabled or disabled on one thread while other threads are
328 // accessing the enabled flag. We don't care whether edge-case events are 366 // accessing the enabled flag. We don't care whether edge-case events are
329 // traced or not, so we allow races on the enabled flag to keep the trace 367 // traced or not, so we allow races on the enabled flag to keep the trace
330 // macros fast. 368 // macros fast.
331 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: 369 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots:
332 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), 370 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled),
333 // "trace_event category enabled"); 371 // "trace_event category enabled");
334 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { 372 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) {
335 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], 373 ANNOTATE_BENIGN_RACE(&g_category_enabled[i],
336 "trace_event category enabled"); 374 "trace_event category enabled");
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 for (int i = 0; i < g_category_index; i++) { 437 for (int i = 0; i < g_category_index; i++) {
400 if (strcmp(g_categories[i], name) == 0) 438 if (strcmp(g_categories[i], name) == 0)
401 return &g_category_enabled[i]; 439 return &g_category_enabled[i];
402 } 440 }
403 441
404 // Create a new category 442 // Create a new category
405 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << 443 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) <<
406 "must increase TRACE_EVENT_MAX_CATEGORIES"; 444 "must increase TRACE_EVENT_MAX_CATEGORIES";
407 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { 445 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) {
408 int new_index = g_category_index++; 446 int new_index = g_category_index++;
409 g_categories[new_index] = name; 447 // Don't hold on to the name pointer, so that we can create categories with
448 // strings not known at compile time (this is required by SetWatchEvent).
449 const char* new_name = base::strdup(name);
450 ANNOTATE_LEAKING_OBJECT_PTR(new_name);
451 g_categories[new_index] = new_name;
410 DCHECK(!g_category_enabled[new_index]); 452 DCHECK(!g_category_enabled[new_index]);
411 if (enabled_) { 453 if (enabled_) {
412 // Note that if both included and excluded_categories are empty, the else 454 // Note that if both included and excluded_categories are empty, the else
413 // clause below excludes nothing, thereby enabling this category. 455 // clause below excludes nothing, thereby enabling this category.
414 if (!included_categories_.empty()) 456 if (!included_categories_.empty())
415 EnableMatchingCategory(new_index, included_categories_, 1); 457 EnableMatchingCategory(new_index, included_categories_, 1);
416 else 458 else
417 EnableMatchingCategory(new_index, excluded_categories_, 0); 459 EnableMatchingCategory(new_index, excluded_categories_, 0);
418 } else { 460 } else {
419 g_category_enabled[new_index] = 0; 461 g_category_enabled[new_index] = 0;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 std::vector<std::string>* included_out, 526 std::vector<std::string>* included_out,
485 std::vector<std::string>* excluded_out) { 527 std::vector<std::string>* excluded_out) {
486 AutoLock lock(lock_); 528 AutoLock lock(lock_);
487 if (enabled_) { 529 if (enabled_) {
488 *included_out = included_categories_; 530 *included_out = included_categories_;
489 *excluded_out = excluded_categories_; 531 *excluded_out = excluded_categories_;
490 } 532 }
491 } 533 }
492 534
493 void TraceLog::SetDisabled() { 535 void TraceLog::SetDisabled() {
494 { 536 AutoLock lock(lock_);
495 AutoLock lock(lock_); 537 if (!enabled_)
496 if (!enabled_) 538 return;
497 return;
498 539
499 if (dispatching_to_observer_list_) { 540 if (dispatching_to_observer_list_) {
500 DLOG(ERROR) 541 DLOG(ERROR)
501 << "Cannot manipulate TraceLog::Enabled state from an observer."; 542 << "Cannot manipulate TraceLog::Enabled state from an observer.";
502 return; 543 return;
503 } 544 }
504 545
505 dispatching_to_observer_list_ = true; 546 dispatching_to_observer_list_ = true;
506 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, 547 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
507 OnTraceLogWillDisable()); 548 OnTraceLogWillDisable());
508 dispatching_to_observer_list_ = false; 549 dispatching_to_observer_list_ = false;
509 550
510 enabled_ = false; 551 enabled_ = false;
511 included_categories_.clear(); 552 included_categories_.clear();
512 excluded_categories_.clear(); 553 excluded_categories_.clear();
513 for (int i = 0; i < g_category_index; i++) 554 watch_category_ = NULL;
514 g_category_enabled[i] = 0; 555 watch_event_name_ = "";
515 AddThreadNameMetadataEvents(); 556 for (int i = 0; i < g_category_index; i++)
516 AddClockSyncMetadataEvents(); 557 g_category_enabled[i] = 0;
517 } // release lock 558 AddThreadNameMetadataEvents();
518 Flush(); 559 AddClockSyncMetadataEvents();
519 } 560 }
520 561
521 void TraceLog::SetEnabled(bool enabled) { 562 void TraceLog::SetEnabled(bool enabled) {
522 if (enabled) 563 if (enabled)
523 SetEnabled(std::vector<std::string>(), std::vector<std::string>()); 564 SetEnabled(std::vector<std::string>(), std::vector<std::string>());
524 else 565 else
525 SetDisabled(); 566 SetDisabled();
526 } 567 }
527 568
528 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { 569 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) {
529 enabled_state_observer_list_.AddObserver(listener); 570 enabled_state_observer_list_.AddObserver(listener);
530 } 571 }
531 572
532 void TraceLog::RemoveEnabledStateObserver( 573 void TraceLog::RemoveEnabledStateObserver(
533 EnabledStateChangedObserver* listener) { 574 EnabledStateChangedObserver* listener) {
534 enabled_state_observer_list_.RemoveObserver(listener); 575 enabled_state_observer_list_.RemoveObserver(listener);
535 } 576 }
536 577
537 float TraceLog::GetBufferPercentFull() const { 578 float TraceLog::GetBufferPercentFull() const {
538 return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize); 579 return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize);
539 } 580 }
540 581
541 void TraceLog::SetOutputCallback(const TraceLog::OutputCallback& cb) { 582 void TraceLog::SetNotificationCallback(
583 const TraceLog::NotificationCallback& cb) {
542 AutoLock lock(lock_); 584 AutoLock lock(lock_);
543 output_callback_ = cb; 585 // Wait until other threads are done using the callback.
586 while (notification_thread_count_ > 0)
587 notification_condition_.Wait();
588 notification_callback_ = cb;
544 } 589 }
545 590
546 void TraceLog::SetBufferFullCallback(const TraceLog::BufferFullCallback& cb) { 591 void TraceLog::Flush(const TraceLog::OutputCallback& cb) {
547 AutoLock lock(lock_);
548 buffer_full_callback_ = cb;
549 }
550
551 void TraceLog::Flush() {
552 std::vector<TraceEvent> previous_logged_events; 592 std::vector<TraceEvent> previous_logged_events;
553 OutputCallback output_callback_copy;
554 { 593 {
555 AutoLock lock(lock_); 594 AutoLock lock(lock_);
556 previous_logged_events.swap(logged_events_); 595 previous_logged_events.swap(logged_events_);
557 output_callback_copy = output_callback_;
558 } // release lock 596 } // release lock
559 597
560 if (output_callback_copy.is_null())
561 return;
562
563 for (size_t i = 0; 598 for (size_t i = 0;
564 i < previous_logged_events.size(); 599 i < previous_logged_events.size();
565 i += kTraceEventBatchSize) { 600 i += kTraceEventBatchSize) {
566 scoped_refptr<RefCountedString> json_events_str_ptr = 601 scoped_refptr<RefCountedString> json_events_str_ptr =
567 new RefCountedString(); 602 new RefCountedString();
568 TraceEvent::AppendEventsAsJSON(previous_logged_events, 603 TraceEvent::AppendEventsAsJSON(previous_logged_events,
569 i, 604 i,
570 kTraceEventBatchSize, 605 kTraceEventBatchSize,
571 &(json_events_str_ptr->data())); 606 &(json_events_str_ptr->data()));
572 output_callback_copy.Run(json_events_str_ptr); 607 cb.Run(json_events_str_ptr);
573 } 608 }
574 } 609 }
575 610
576 int TraceLog::AddTraceEvent(char phase, 611 int TraceLog::AddTraceEvent(char phase,
577 const unsigned char* category_enabled, 612 const unsigned char* category_enabled,
578 const char* name, 613 const char* name,
579 unsigned long long id, 614 unsigned long long id,
580 int num_args, 615 int num_args,
581 const char** arg_names, 616 const char** arg_names,
582 const unsigned char* arg_types, 617 const unsigned char* arg_types,
583 const unsigned long long* arg_values, 618 const unsigned long long* arg_values,
584 int threshold_begin_id, 619 int threshold_begin_id,
585 long long threshold, 620 long long threshold,
586 unsigned char flags) { 621 unsigned char flags) {
587 DCHECK(name); 622 DCHECK(name);
588 TimeTicks now = TimeTicks::NowFromSystemTraceTime(); 623 TimeTicks now = TimeTicks::NowFromSystemTraceTime();
589 BufferFullCallback buffer_full_callback_copy; 624 NotificationHelper notifier(this);
590 int ret_begin_id = -1; 625 int ret_begin_id = -1;
591 { 626 {
592 AutoLock lock(lock_); 627 AutoLock lock(lock_);
593 if (!*category_enabled) 628 if (!*category_enabled)
594 return -1; 629 return -1;
595 if (logged_events_.size() >= kTraceEventBufferSize) 630 if (logged_events_.size() >= kTraceEventBufferSize)
596 return -1; 631 return -1;
597 632
598 int thread_id = static_cast<int>(PlatformThread::CurrentId()); 633 int thread_id = static_cast<int>(PlatformThread::CurrentId());
599 634
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) 680 if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
646 id ^= process_id_hash_; 681 id ^= process_id_hash_;
647 682
648 ret_begin_id = static_cast<int>(logged_events_.size()); 683 ret_begin_id = static_cast<int>(logged_events_.size());
649 logged_events_.push_back( 684 logged_events_.push_back(
650 TraceEvent(thread_id, 685 TraceEvent(thread_id,
651 now, phase, category_enabled, name, id, 686 now, phase, category_enabled, name, id,
652 num_args, arg_names, arg_types, arg_values, 687 num_args, arg_names, arg_types, arg_values,
653 flags)); 688 flags));
654 689
655 if (logged_events_.size() == kTraceEventBufferSize) { 690 if (logged_events_.size() == kTraceEventBufferSize)
656 buffer_full_callback_copy = buffer_full_callback_; 691 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL);
657 } 692
693 if (watch_category_ == category_enabled && watch_event_name_ == name)
694 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
658 } // release lock 695 } // release lock
659 696
660 if (!buffer_full_callback_copy.is_null()) 697 notifier.SendNotificationIfAny();
661 buffer_full_callback_copy.Run();
662 698
663 return ret_begin_id; 699 return ret_begin_id;
664 } 700 }
665 701
666 void TraceLog::AddTraceEventEtw(char phase, 702 void TraceLog::AddTraceEventEtw(char phase,
667 const char* name, 703 const char* name,
668 const void* id, 704 const void* id,
669 const char* extra) { 705 const char* extra) {
670 #if defined(OS_WIN) 706 #if defined(OS_WIN)
671 TraceEventETWProvider::Trace(name, phase, id, extra); 707 TraceEventETWProvider::Trace(name, phase, id, extra);
672 #endif 708 #endif
673 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, 709 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
674 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); 710 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
675 } 711 }
676 712
677 void TraceLog::AddTraceEventEtw(char phase, 713 void TraceLog::AddTraceEventEtw(char phase,
678 const char* name, 714 const char* name,
679 const void* id, 715 const void* id,
680 const std::string& extra) 716 const std::string& extra)
681 { 717 {
682 #if defined(OS_WIN) 718 #if defined(OS_WIN)
683 TraceEventETWProvider::Trace(name, phase, id, extra); 719 TraceEventETWProvider::Trace(name, phase, id, extra);
684 #endif 720 #endif
685 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, 721 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
686 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); 722 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
687 } 723 }
688 724
725 void TraceLog::SetWatchEvent(const std::string& category_name,
726 const std::string& event_name) {
727 const unsigned char* category = GetCategoryEnabled(category_name.c_str());
728 int notify_count = 0;
729 {
730 AutoLock lock(lock_);
731 watch_category_ = category;
732 watch_event_name_ = event_name;
733
734 // First, search existing events for watch event because we want to catch it
735 // even if it has already occurred.
736 for (size_t i = 0u; i < logged_events_.size(); ++i) {
737 if (category == logged_events_[i].category_enabled() &&
738 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) {
739 ++notify_count;
740 }
741 }
742 } // release lock
743
744 // Send notification for each event found.
745 for (int i = 0; i < notify_count; ++i) {
746 NotificationHelper notifier(this);
747 lock_.Acquire();
748 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
749 lock_.Release();
750 notifier.SendNotificationIfAny();
751 }
752 }
753
754 void TraceLog::CancelWatchEvent() {
755 AutoLock lock(lock_);
756 watch_category_ = NULL;
757 watch_event_name_ = "";
758 }
759
689 void TraceLog::AddClockSyncMetadataEvents() { 760 void TraceLog::AddClockSyncMetadataEvents() {
690 #if defined(OS_ANDROID) 761 #if defined(OS_ANDROID)
691 // Since Android does not support sched_setaffinity, we cannot establish clock 762 // Since Android does not support sched_setaffinity, we cannot establish clock
692 // sync unless the scheduler clock is set to global. If the trace_clock file 763 // sync unless the scheduler clock is set to global. If the trace_clock file
693 // can't be read, we will assume the kernel doesn't support tracing and do 764 // can't be read, we will assume the kernel doesn't support tracing and do
694 // nothing. 765 // nothing.
695 std::string clock_mode; 766 std::string clock_mode;
696 if (!file_util::ReadFileToString( 767 if (!file_util::ReadFileToString(
697 FilePath("/sys/kernel/debug/tracing/trace_clock"), 768 FilePath("/sys/kernel/debug/tracing/trace_clock"),
698 &clock_mode)) 769 &clock_mode))
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 // Create a FNV hash from the process ID for XORing. 831 // Create a FNV hash from the process ID for XORing.
761 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details. 832 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details.
762 unsigned long long offset_basis = 14695981039346656037ull; 833 unsigned long long offset_basis = 14695981039346656037ull;
763 unsigned long long fnv_prime = 1099511628211ull; 834 unsigned long long fnv_prime = 1099511628211ull;
764 unsigned long long pid = static_cast<unsigned long long>(process_id_); 835 unsigned long long pid = static_cast<unsigned long long>(process_id_);
765 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; 836 process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
766 } 837 }
767 838
768 } // namespace debug 839 } // namespace debug
769 } // namespace base 840 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698