Skip to content

Commit f6b53db

Browse files
Jamie GennisAndroid (Google) Code Review
authored andcommitted
Merge "libutils: add a system-wide tracing utility"
2 parents fa28f57 + f217df6 commit f6b53db

File tree

3 files changed

+215
-1
lines changed

3 files changed

+215
-1
lines changed

include/utils/Trace.h

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef ANDROID_TRACE_H
18+
#define ANDROID_TRACE_H
19+
20+
#include <fcntl.h>
21+
#include <stdint.h>
22+
#include <stdio.h>
23+
#include <string.h>
24+
#include <sys/stat.h>
25+
#include <sys/types.h>
26+
#include <unistd.h>
27+
28+
#include <cutils/compiler.h>
29+
#include <utils/threads.h>
30+
31+
// The ATRACE_TAG macro can be defined before including this header to trace
32+
// using one of the tags defined below. It must be defined to one of the
33+
// following ATRACE_TAG_* macros. The trace tag is used to filter tracing in
34+
// userland to avoid some of the runtime cost of tracing when it is not desired.
35+
//
36+
// Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
37+
// being enabled - this should ONLY be done for debug code, as userland tracing
38+
// has a performance cost even when the trace is not being recorded. Defining
39+
// ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
40+
// in the tracing always being disabled.
41+
#define ATRACE_TAG_NEVER 0 // The "never" tag is never enabled.
42+
#define ATRACE_TAG_ALWAYS (1<<0) // The "always" tag is always enabled.
43+
#define ATRACE_TAG_GRAPHICS (1<<1)
44+
#define ATRACE_TAG_LAST (1<<1)
45+
46+
#define ATRACE_TAG_INVALID (~((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST))
47+
48+
#ifndef ATRACE_TAG
49+
#define ATRACE_TAG ATRACE_TAG_NEVER
50+
#elif ATRACE_TAG > ATRACE_TAG_LAST
51+
#error ATRACE_TAG must be defined to be one of the tags defined in utils/Trace.h
52+
#endif
53+
54+
// ATRACE_CALL traces the beginning and end of the current function. To trace
55+
// the correct start and end times this macro should be the first line of the
56+
// function body.
57+
#define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)
58+
59+
// ATRACE_INT traces a named integer value. This can be used to track how the
60+
// value changes over time in a trace.
61+
#define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
62+
63+
namespace android {
64+
65+
class Tracer {
66+
67+
public:
68+
69+
static inline void traceCounter(uint64_t tag, const char* name,
70+
int32_t value) {
71+
if (!android_atomic_acquire_load(&sIsReady)) {
72+
init();
73+
}
74+
int traceFD = sTraceFD;
75+
if (CC_UNLIKELY(tagEnabled(tag) && traceFD != -1)) {
76+
char buf[1024];
77+
snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value);
78+
write(traceFD, buf, strlen(buf));
79+
}
80+
}
81+
82+
static inline void traceBegin(uint64_t tag, const char* name) {
83+
if (CC_UNLIKELY(!android_atomic_acquire_load(&sIsReady))) {
84+
init();
85+
}
86+
int traceFD = sTraceFD;
87+
if (CC_UNLIKELY(tagEnabled(tag) && (traceFD != -1))) {
88+
char buf[1024];
89+
size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name);
90+
write(traceFD, buf, len);
91+
}
92+
}
93+
94+
static inline void traceEnd(uint64_t tag) {
95+
if (CC_UNLIKELY(!android_atomic_acquire_load(&sIsReady))) {
96+
init();
97+
}
98+
int traceFD = sTraceFD;
99+
if (CC_UNLIKELY(tagEnabled(tag) && (traceFD != -1))) {
100+
char buf = 'E';
101+
write(traceFD, &buf, 1);
102+
}
103+
}
104+
105+
private:
106+
107+
static inline bool tagEnabled(uint64_t tag) {
108+
return !(tag & ATRACE_TAG_INVALID) && (tag & sEnabledTags);
109+
}
110+
111+
// init opens the trace marker file for writing and reads the
112+
// atrace.tags.enableflags system property. It does this only the first
113+
// time it is run, using sMutex for synchronization.
114+
static void init();
115+
116+
// sIsReady is a boolean value indicating whether a call to init() has
117+
// completed in this process. It is initialized to 0 and set to 1 when the
118+
// first init() call completes. It is set to 1 even if a failure occurred
119+
// in init (e.g. the trace marker file couldn't be opened).
120+
//
121+
// This should be checked by all tracing functions using an atomic acquire
122+
// load operation before calling init(). This check avoids the need to lock
123+
// a mutex each time a trace function gets called.
124+
static volatile int32_t sIsReady;
125+
126+
// sTraceFD is the file descriptor used to write to the kernel's trace
127+
// buffer. It is initialized to -1 and set to an open file descriptor in
128+
// init() while a lock on sMutex is held.
129+
//
130+
// This should only be used by a trace function after init() has
131+
// successfully completed.
132+
static int sTraceFD;
133+
134+
// sEnabledTags is the set of tag bits for which tracing is currently
135+
// enabled. It is initialized to 0 and set based on the
136+
// atrace.tags.enableflags system property in init() while a lock on sMutex
137+
// is held.
138+
//
139+
// This should only be used by a trace function after init() has
140+
// successfully completed.
141+
static uint64_t sEnabledTags;
142+
143+
// sMutex is used to protect the execution of init().
144+
static Mutex sMutex;
145+
};
146+
147+
class ScopedTrace {
148+
149+
public:
150+
inline ScopedTrace(uint64_t tag, const char* name) :
151+
mTag(tag) {
152+
Tracer::traceBegin(mTag, name);
153+
}
154+
155+
inline ~ScopedTrace() {
156+
Tracer::traceEnd(mTag);
157+
}
158+
159+
private:
160+
161+
uint64_t mTag;
162+
};
163+
164+
}; // namespace android
165+
166+
#endif // ANDROID_TRACE_H

libs/utils/Android.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ include $(CLEAR_VARS)
7777
# we have the common sources, plus some device-specific stuff
7878
LOCAL_SRC_FILES:= \
7979
$(commonSources) \
80-
Looper.cpp
80+
Looper.cpp \
81+
Trace.cpp
8182

8283
ifeq ($(TARGET_OS),linux)
8384
LOCAL_LDLIBS += -lrt -ldl

libs/utils/Trace.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <cutils/properties.h>
18+
#include <utils/Log.h>
19+
#include <utils/Trace.h>
20+
21+
namespace android {
22+
23+
volatile int32_t Tracer::sIsReady = 0;
24+
int Tracer::sTraceFD = -1;
25+
uint64_t Tracer::sEnabledTags = 0;
26+
Mutex Tracer::sMutex;
27+
28+
void Tracer::init() {
29+
Mutex::Autolock lock(sMutex);
30+
31+
if (!sIsReady) {
32+
const char* const traceFileName =
33+
"/sys/kernel/debug/tracing/trace_marker";
34+
sTraceFD = open(traceFileName, O_WRONLY);
35+
if (sTraceFD == -1) {
36+
ALOGE("error opening trace file: %s (%d)", strerror(errno), errno);
37+
} else {
38+
char value[PROPERTY_VALUE_MAX];
39+
property_get("atrace.tags.enableflags", value, "0");
40+
sEnabledTags = strtoll(value, NULL, 0) | ATRACE_TAG_ALWAYS;
41+
}
42+
43+
android_atomic_release_store(1, &sIsReady);
44+
}
45+
}
46+
47+
} // namespace andoid

0 commit comments

Comments
 (0)