1e1c7845aa
Some global static variables are only used within a single function, so moving them inside the function which requires them. This also ensures those static variables of class types are initialized before they are being used. For example, this is needed for CachedProperty(), as some of the member method, e.g., CachedProperty().Get(), might be invoked, e.g., in __libc_preinit(), before the constructor is invoked. This happens after we added property trace points in commit Id2b93acb2ce02b308c0e4889f836159151af3b46. For g_lock, we don't move them because it can be initialized by setting its memory to 0. And it's used in two functions. https://android.googlesource.com/platform/bionic/+/refs/heads/master/libc/private/bionic_lock.h Bug: 147275573 Test: atest CtsBionicTestCases Test: adb shell perfetto -o /data/misc/perfetto-traces/test_trace -t 10s bionic sysprop Change-Id: I99565ce2442d34f33830778915c737eed834f8b3
112 lines
2.9 KiB
C++
112 lines
2.9 KiB
C++
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "private/bionic_systrace.h"
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <async_safe/log.h>
|
|
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
|
|
|
|
#include "private/CachedProperty.h"
|
|
#include "private/bionic_lock.h"
|
|
|
|
#define WRITE_OFFSET 32
|
|
|
|
static Lock g_lock;
|
|
|
|
bool should_trace(const uint64_t enable_tags) {
|
|
static uint64_t tags_val;
|
|
static CachedProperty tags_prop(kTraceTagsProp);
|
|
g_lock.lock();
|
|
if (tags_prop.DidChange()) {
|
|
tags_val = strtoull(tags_prop.Get(), nullptr, 0);
|
|
}
|
|
g_lock.unlock();
|
|
return tags_val & enable_tags;
|
|
}
|
|
|
|
int get_trace_marker_fd() {
|
|
static int opened_trace_marker_fd = -1;
|
|
g_lock.lock();
|
|
if (opened_trace_marker_fd == -1) {
|
|
opened_trace_marker_fd = open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
|
|
if (opened_trace_marker_fd == -1) {
|
|
opened_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
|
|
}
|
|
}
|
|
g_lock.unlock();
|
|
return opened_trace_marker_fd;
|
|
}
|
|
|
|
// event could be 'B' for begin or 'E' for end.
|
|
void output_trace(const char* message, const char event) {
|
|
int trace_marker_fd = get_trace_marker_fd();
|
|
if (trace_marker_fd == -1) {
|
|
return;
|
|
}
|
|
|
|
// If bionic tracing has been enabled, then write the message to the
|
|
// kernel trace_marker.
|
|
int length = strlen(message);
|
|
char buf[length + WRITE_OFFSET];
|
|
size_t len =
|
|
async_safe_format_buffer(buf, length + WRITE_OFFSET, "%c|%d|%s", event, getpid(), message);
|
|
|
|
// Tracing may stop just after checking property and before writing the message.
|
|
// So the write is acceptable to fail. See b/20666100.
|
|
TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
|
|
}
|
|
|
|
void bionic_trace_begin(const char* message) {
|
|
if (!should_trace()) {
|
|
return;
|
|
}
|
|
|
|
output_trace(message);
|
|
}
|
|
|
|
void bionic_trace_end() {
|
|
if (!should_trace()) {
|
|
return;
|
|
}
|
|
|
|
int trace_marker_fd = get_trace_marker_fd();
|
|
if (trace_marker_fd == -1) {
|
|
return;
|
|
}
|
|
|
|
TEMP_FAILURE_RETRY(write(trace_marker_fd, "E|", 2));
|
|
}
|
|
|
|
ScopedTrace::ScopedTrace(const char* message) : called_end_(false) {
|
|
bionic_trace_begin(message);
|
|
}
|
|
|
|
ScopedTrace::~ScopedTrace() {
|
|
End();
|
|
}
|
|
|
|
void ScopedTrace::End() {
|
|
if (!called_end_) {
|
|
bionic_trace_end();
|
|
called_end_ = true;
|
|
}
|
|
}
|