summaryrefslogtreecommitdiffstats
path: root/base/debug/trace_event.h
diff options
context:
space:
mode:
authorjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-21 12:28:59 +0000
committerjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-21 12:28:59 +0000
commitd1f0351663137617d0f68e03051c6fc26cad5ab0 (patch)
treef65399952ef82c8966dfd70a4e7d1a15b475d727 /base/debug/trace_event.h
parentd27b1505c3fbfff5e41ba6cf28ca65d413d03b2b (diff)
downloadchromium_src-d1f0351663137617d0f68e03051c6fc26cad5ab0.zip
chromium_src-d1f0351663137617d0f68e03051c6fc26cad5ab0.tar.gz
chromium_src-d1f0351663137617d0f68e03051c6fc26cad5ab0.tar.bz2
Allow trace event to work with temporary name strings.
This is needed where the name or arg_names may not be available as compile time constants. BUG=None TEST=base_unittests --gtest_filter=TraceEvent* Review URL: http://codereview.chromium.org/7354025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93375 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug/trace_event.h')
-rw-r--r--base/debug/trace_event.h95
1 files changed, 68 insertions, 27 deletions
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index 2162091..11b8318 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -37,6 +37,21 @@
// tracing and display data collected across all active processes.
//
//
+// Memory scoping note:
+// Tracing copies the pointers, not the string content, of the strings passed
+// in for category, name, and arg_names. Thus, the following code will
+// cause problems:
+// char* str = strdup("impprtantName");
+// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
+// free(str); // Trace system now has dangling pointer
+//
+// To avoid this issue with the |name| and |arg_name| parameters, use the
+// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
+// Notes: The category must always be in a long-lived char* (i.e. static const).
+// The |arg_values|, when used, are always deep copied and so never have
+// this restriction.
+//
+//
// Thread Safety:
// A thread safe singleton and mutex are used for thread safety. Category
// enabled flags are used to limit the performance impact when the system
@@ -122,7 +137,15 @@
#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_INSTANT, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val)
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, false)
+#define TRACE_EVENT_COPY_INSTANT0(category, name) \
+ TRACE_EVENT_COPY_INSTANT1(category, name, NULL, 0)
+#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
+ TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, NULL, 0)
+#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_INSTANT, \
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, true)
// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
// associated arguments. If the category is not enabled, then this
@@ -136,7 +159,15 @@
#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_BEGIN, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val)
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, false)
+#define TRACE_EVENT_COPY_BEGIN0(category, name) \
+ TRACE_EVENT_COPY_BEGIN1(category, name, NULL, 0)
+#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
+ TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, NULL, 0)
+#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_BEGIN, \
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, true)
// Records a single END event for "name" immediately. If the category
// is not enabled, then this does nothing.
@@ -149,7 +180,15 @@
#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_END, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val)
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, false)
+#define TRACE_EVENT_COPY_END0(category, name) \
+ TRACE_EVENT_COPY_END1(category, name, NULL, 0)
+#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
+ TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, NULL, 0)
+#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_END, \
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, true)
// Time threshold event:
// Only record the event if the duration is greater than the specified
@@ -195,12 +234,12 @@
// Implementation detail: internal macro to create static category and add begin
// event if the category is enabled.
#define INTERNAL_TRACE_EVENT_ADD( \
- phase, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+ phase, category, name, arg1_name, arg1_val, arg2_name, arg2_val, copy) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
if (INTERNAL_TRACE_EVENT_UID(catstatic)->enabled) { \
base::debug::TraceLog::GetInstance()->AddTraceEvent( \
phase, INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0); \
+ name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, copy); \
}
// Implementation detail: internal macro to create static category and add begin
@@ -215,7 +254,7 @@
base::debug::TraceLog::GetInstance()->AddTraceEvent( \
base::debug::TRACE_EVENT_PHASE_BEGIN, \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0); \
+ name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, false); \
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
INTERNAL_TRACE_EVENT_UID(catstatic), name); \
}
@@ -233,12 +272,14 @@
base::debug::TraceLog::GetInstance()->AddTraceEvent( \
base::debug::TRACE_EVENT_PHASE_BEGIN, \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0); \
+ name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, false); \
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
INTERNAL_TRACE_EVENT_UID(catstatic), name, \
INTERNAL_TRACE_EVENT_UID(begin_event_id), threshold); \
}
+class RefCountedBytes;
+
namespace base {
namespace debug {
@@ -310,47 +351,42 @@ class BASE_API TraceValue {
value_.as_pointer = rhs;
}
TraceValue(const char* rhs) : type_(TRACE_TYPE_STRING) {
- value_.as_string_refptr = new RefCountedString();
- value_.as_string_refptr->AddRef();
- DCHECK(value_.as_string_refptr->HasOneRef());
- value_.as_string_refptr->data = rhs;
- }
- TraceValue(const TraceValue& rhs) : type_(TRACE_TYPE_UNDEFINED) {
- operator=(rhs);
- }
- ~TraceValue() {
- Destroy();
+ value_.as_string = rhs;
}
- TraceValue& operator=(const TraceValue& rhs);
-
- void Destroy();
-
void AppendAsJSON(std::string* out) const;
Type type() const {
return type_;
}
uint64 as_uint() const {
+ DCHECK_EQ(TRACE_TYPE_UINT, type_);
return value_.as_uint;
}
bool as_bool() const {
+ DCHECK_EQ(TRACE_TYPE_BOOL, type_);
return value_.as_bool;
}
int64 as_int() const {
+ DCHECK_EQ(TRACE_TYPE_INT, type_);
return value_.as_int;
}
double as_double() const {
+ DCHECK_EQ(TRACE_TYPE_DOUBLE, type_);
return value_.as_double;
}
const void* as_pointer() const {
+ DCHECK_EQ(TRACE_TYPE_POINTER, type_);
return value_.as_pointer;
}
const char* as_string() const {
- return value_.as_string_refptr->data.c_str();
+ DCHECK_EQ(TRACE_TYPE_STRING, type_);
+ return value_.as_string;
+ }
+ const char** as_assignable_string() {
+ DCHECK_EQ(TRACE_TYPE_STRING, type_);
+ return &value_.as_string;
}
-
- typedef RefCountedData<std::string> RefCountedString;
private:
union Value {
@@ -359,7 +395,7 @@ class BASE_API TraceValue {
int64 as_int;
double as_double;
const void* as_pointer;
- RefCountedString* as_string_refptr;
+ const char* as_string;
};
Type type_;
@@ -380,7 +416,8 @@ class TraceEvent {
const TraceCategory* category,
const char* name,
const char* arg1_name, const TraceValue& arg1_val,
- const char* arg2_name, const TraceValue& arg2_val);
+ const char* arg2_name, const TraceValue& arg2_val,
+ bool copy);
~TraceEvent();
// Serialize event data to JSON
@@ -401,6 +438,7 @@ class TraceEvent {
const char* name_;
const char* arg_names_[kTraceMaxNumArgs];
TraceValue arg_values_[kTraceMaxNumArgs];
+ scoped_refptr<RefCountedBytes> parameter_copy_storage_;
};
@@ -441,13 +479,16 @@ class BASE_API TraceLog {
// On end events, the return value of the begin event can be specified along
// with a threshold in microseconds. If the elapsed time between begin and end
// is less than the threshold, the begin/end event pair is dropped.
+ // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
+ // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
int AddTraceEvent(TraceEventPhase phase,
const TraceCategory* category,
const char* name,
const char* arg1_name, TraceValue arg1_val,
const char* arg2_name, TraceValue arg2_val,
int threshold_begin_id,
- int64 threshold);
+ int64 threshold,
+ bool copy);
static void AddTraceEventEtw(TraceEventPhase phase,
const char* name,
const void* id,