2018-05-04 14:27:53 +08:00
|
|
|
//===-- xray_basic_logging.cc -----------------------------------*- C++ -*-===//
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of XRay, a dynamic runtime instrumentation system.
|
|
|
|
//
|
|
|
|
// Implementation of a simple in-memory log of XRay events. This defines a
|
|
|
|
// logging function that's compatible with the XRay handler interface, and
|
|
|
|
// routines for exporting data to files.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include <cassert>
|
2017-10-05 13:45:51 +08:00
|
|
|
#include <cstring>
|
2017-08-02 12:51:40 +08:00
|
|
|
#include <errno.h>
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
#include <fcntl.h>
|
2017-11-21 15:29:21 +08:00
|
|
|
#include <pthread.h>
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
#include <sys/types.h>
|
2017-08-02 12:51:40 +08:00
|
|
|
#include <time.h>
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
#include <unistd.h>
|
2016-09-20 22:35:57 +08:00
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
#include "sanitizer_common/sanitizer_allocator_internal.h"
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
#include "sanitizer_common/sanitizer_libc.h"
|
|
|
|
#include "xray/xray_records.h"
|
2018-06-06 14:07:48 +08:00
|
|
|
#include "xray_recursion_guard.h"
|
2018-05-04 14:27:53 +08:00
|
|
|
#include "xray_basic_flags.h"
|
|
|
|
#include "xray_basic_logging.h"
|
2016-11-16 09:01:13 +08:00
|
|
|
#include "xray_defs.h"
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
#include "xray_flags.h"
|
|
|
|
#include "xray_interface_internal.h"
|
2017-02-11 04:30:43 +08:00
|
|
|
#include "xray_tsc.h"
|
[XRay][compiler-rt] XRay Flight Data Recorder Mode
Summary:
In this change we introduce the notion of a "flight data recorder" mode
for XRay logging, where XRay logs in-memory first, and write out data
on-demand as required (as opposed to the naive implementation that keeps
logging while tracing is "on"). This depends on D26232 where we
implement the core data structure for holding the buffers that threads
will be using to write out records of operation.
This implementation only currently works on x86_64 and depends heavily
on the TSC math to write out smaller records to the inmemory buffers.
Also, this implementation defines two different kinds of records with
different sizes (compared to the current naive implementation): a
MetadataRecord (16 bytes) and a FunctionRecord (8 bytes). MetadataRecord
entries are meant to write out information like the thread ID for which
the metadata record is defined for, whether the execution of a thread
moved to a different CPU, etc. while a FunctionRecord represents the
different kinds of function call entry/exit records we might encounter
in the course of a thread's execution along with a delta from the last
time the logging handler was called.
While this implementation is not exactly what is described in the
original XRay whitepaper, this one gives us an initial implementation
that we can iterate and build upon.
Reviewers: echristo, rSerge, majnemer
Subscribers: mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D27038
llvm-svn: 293015
2017-01-25 11:50:46 +08:00
|
|
|
#include "xray_utils.h"
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
|
|
|
|
namespace __xray {
|
|
|
|
|
2018-06-05 14:12:42 +08:00
|
|
|
SpinMutex LogMutex;
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
// We use elements of this type to record the entry TSC of every function ID we
|
|
|
|
// see as we're tracing a particular thread's execution.
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
struct alignas(16) StackEntry {
|
2017-11-21 15:29:21 +08:00
|
|
|
int32_t FuncId;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
uint16_t Type;
|
|
|
|
uint8_t CPU;
|
|
|
|
uint8_t Padding;
|
2017-11-21 15:29:21 +08:00
|
|
|
uint64_t TSC;
|
|
|
|
};
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
static_assert(sizeof(StackEntry) == 16, "Wrong size for StackEntry");
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
struct alignas(64) ThreadLocalData {
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
void *InMemoryBuffer = nullptr;
|
2017-11-21 15:29:21 +08:00
|
|
|
size_t BufferSize = 0;
|
|
|
|
size_t BufferOffset = 0;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
void *ShadowStack = nullptr;
|
2017-11-21 15:29:21 +08:00
|
|
|
size_t StackSize = 0;
|
|
|
|
size_t StackEntries = 0;
|
|
|
|
int Fd = -1;
|
Add Xray instrumentation support to FreeBSD
Summary:
- Enabling the build.
- Using assembly for the cpuid parts.
- Using thr_self FreeBSD call to get the thread id
Patch by: David CARLIER
Reviewers: dberris, rnk, krytarowski
Reviewed By: dberris, krytarowski
Subscribers: emaste, stevecheckoway, nglevin, srhines, kubamracek, dberris, mgorny, krytarowski, llvm-commits, #sanitizers
Differential Revision: https://reviews.llvm.org/D43278
llvm-svn: 325240
2018-02-15 22:17:15 +08:00
|
|
|
tid_t TID = 0;
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
};
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
static pthread_key_t PThreadKey;
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
|
2018-06-05 14:12:42 +08:00
|
|
|
static atomic_uint8_t BasicInitialized{0};
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
BasicLoggingOptions GlobalOptions;
|
|
|
|
|
2018-06-06 14:07:48 +08:00
|
|
|
thread_local atomic_uint8_t Guard{0};
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
|
|
|
|
static uint64_t thresholdTicks() XRAY_NEVER_INSTRUMENT {
|
|
|
|
static uint64_t TicksPerSec = probeRequiredCPUFeatures()
|
|
|
|
? getTSCFrequency()
|
2018-06-05 18:12:58 +08:00
|
|
|
: NanosecondsPerSecond;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
static const uint64_t ThresholdTicks =
|
|
|
|
TicksPerSec * GlobalOptions.DurationFilterMicros / 1000000;
|
|
|
|
return ThresholdTicks;
|
|
|
|
}
|
2017-11-21 15:29:21 +08:00
|
|
|
|
|
|
|
static int openLogFile() XRAY_NEVER_INSTRUMENT {
|
[XRay][compiler-rt] XRay Flight Data Recorder Mode
Summary:
In this change we introduce the notion of a "flight data recorder" mode
for XRay logging, where XRay logs in-memory first, and write out data
on-demand as required (as opposed to the naive implementation that keeps
logging while tracing is "on"). This depends on D26232 where we
implement the core data structure for holding the buffers that threads
will be using to write out records of operation.
This implementation only currently works on x86_64 and depends heavily
on the TSC math to write out smaller records to the inmemory buffers.
Also, this implementation defines two different kinds of records with
different sizes (compared to the current naive implementation): a
MetadataRecord (16 bytes) and a FunctionRecord (8 bytes). MetadataRecord
entries are meant to write out information like the thread ID for which
the metadata record is defined for, whether the execution of a thread
moved to a different CPU, etc. while a FunctionRecord represents the
different kinds of function call entry/exit records we might encounter
in the course of a thread's execution along with a delta from the last
time the logging handler was called.
While this implementation is not exactly what is described in the
original XRay whitepaper, this one gives us an initial implementation
that we can iterate and build upon.
Reviewers: echristo, rSerge, majnemer
Subscribers: mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D27038
llvm-svn: 293015
2017-01-25 11:50:46 +08:00
|
|
|
int F = getLogFD();
|
|
|
|
if (F == -1)
|
2017-01-03 12:04:00 +08:00
|
|
|
return -1;
|
2017-04-18 11:25:11 +08:00
|
|
|
|
|
|
|
// Test for required CPU features and cache the cycle frequency
|
|
|
|
static bool TSCSupported = probeRequiredCPUFeatures();
|
2017-10-05 13:45:51 +08:00
|
|
|
static uint64_t CycleFrequency =
|
2018-06-05 18:12:58 +08:00
|
|
|
TSCSupported ? getTSCFrequency() : NanosecondsPerSecond;
|
2017-04-18 11:25:11 +08:00
|
|
|
|
2017-01-03 12:04:00 +08:00
|
|
|
// Since we're here, we get to write the header. We set it up so that the
|
|
|
|
// header will only be written once, at the start, and let the threads
|
|
|
|
// logging do writes which just append.
|
|
|
|
XRayFileHeader Header;
|
2017-10-05 13:45:51 +08:00
|
|
|
Header.Version = 2; // Version 2 includes tail exit records.
|
2017-01-03 12:04:00 +08:00
|
|
|
Header.Type = FileTypes::NAIVE_LOG;
|
2017-04-18 11:25:11 +08:00
|
|
|
Header.CycleFrequency = CycleFrequency;
|
2017-01-03 12:04:00 +08:00
|
|
|
|
|
|
|
// FIXME: Actually check whether we have 'constant_tsc' and 'nonstop_tsc'
|
|
|
|
// before setting the values in the header.
|
|
|
|
Header.ConstantTSC = 1;
|
|
|
|
Header.NonstopTSC = 1;
|
[XRay][compiler-rt] XRay Flight Data Recorder Mode
Summary:
In this change we introduce the notion of a "flight data recorder" mode
for XRay logging, where XRay logs in-memory first, and write out data
on-demand as required (as opposed to the naive implementation that keeps
logging while tracing is "on"). This depends on D26232 where we
implement the core data structure for holding the buffers that threads
will be using to write out records of operation.
This implementation only currently works on x86_64 and depends heavily
on the TSC math to write out smaller records to the inmemory buffers.
Also, this implementation defines two different kinds of records with
different sizes (compared to the current naive implementation): a
MetadataRecord (16 bytes) and a FunctionRecord (8 bytes). MetadataRecord
entries are meant to write out information like the thread ID for which
the metadata record is defined for, whether the execution of a thread
moved to a different CPU, etc. while a FunctionRecord represents the
different kinds of function call entry/exit records we might encounter
in the course of a thread's execution along with a delta from the last
time the logging handler was called.
While this implementation is not exactly what is described in the
original XRay whitepaper, this one gives us an initial implementation
that we can iterate and build upon.
Reviewers: echristo, rSerge, majnemer
Subscribers: mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D27038
llvm-svn: 293015
2017-01-25 11:50:46 +08:00
|
|
|
retryingWriteAll(F, reinterpret_cast<char *>(&Header),
|
2017-01-03 12:04:00 +08:00
|
|
|
reinterpret_cast<char *>(&Header) + sizeof(Header));
|
[XRay][compiler-rt] XRay Flight Data Recorder Mode
Summary:
In this change we introduce the notion of a "flight data recorder" mode
for XRay logging, where XRay logs in-memory first, and write out data
on-demand as required (as opposed to the naive implementation that keeps
logging while tracing is "on"). This depends on D26232 where we
implement the core data structure for holding the buffers that threads
will be using to write out records of operation.
This implementation only currently works on x86_64 and depends heavily
on the TSC math to write out smaller records to the inmemory buffers.
Also, this implementation defines two different kinds of records with
different sizes (compared to the current naive implementation): a
MetadataRecord (16 bytes) and a FunctionRecord (8 bytes). MetadataRecord
entries are meant to write out information like the thread ID for which
the metadata record is defined for, whether the execution of a thread
moved to a different CPU, etc. while a FunctionRecord represents the
different kinds of function call entry/exit records we might encounter
in the course of a thread's execution along with a delta from the last
time the logging handler was called.
While this implementation is not exactly what is described in the
original XRay whitepaper, this one gives us an initial implementation
that we can iterate and build upon.
Reviewers: echristo, rSerge, majnemer
Subscribers: mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D27038
llvm-svn: 293015
2017-01-25 11:50:46 +08:00
|
|
|
return F;
|
2017-01-03 12:04:00 +08:00
|
|
|
}
|
|
|
|
|
2017-10-05 13:45:51 +08:00
|
|
|
int getGlobalFd() XRAY_NEVER_INSTRUMENT {
|
2017-11-21 15:29:21 +08:00
|
|
|
static int Fd = openLogFile();
|
2017-10-05 13:45:51 +08:00
|
|
|
return Fd;
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
ThreadLocalData &getThreadLocalData() XRAY_NEVER_INSTRUMENT {
|
|
|
|
thread_local ThreadLocalData TLD;
|
|
|
|
thread_local bool UNUSED TOnce = [] {
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
if (GlobalOptions.ThreadBufferSize == 0) {
|
2018-06-05 14:12:42 +08:00
|
|
|
if (Verbosity())
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
Report("Not initializing TLD since ThreadBufferSize == 0.\n");
|
2017-11-21 15:29:21 +08:00
|
|
|
return false;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
}
|
2018-06-05 14:12:42 +08:00
|
|
|
TLD.TID = GetTid();
|
2017-11-21 15:29:21 +08:00
|
|
|
pthread_setspecific(PThreadKey, &TLD);
|
|
|
|
TLD.Fd = getGlobalFd();
|
|
|
|
TLD.InMemoryBuffer = reinterpret_cast<XRayRecord *>(
|
|
|
|
InternalAlloc(sizeof(XRayRecord) * GlobalOptions.ThreadBufferSize,
|
|
|
|
nullptr, alignof(XRayRecord)));
|
|
|
|
TLD.BufferSize = GlobalOptions.ThreadBufferSize;
|
|
|
|
TLD.BufferOffset = 0;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
if (GlobalOptions.MaxStackDepth == 0) {
|
2018-06-05 14:12:42 +08:00
|
|
|
if (Verbosity())
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
Report("Not initializing the ShadowStack since MaxStackDepth == 0.\n");
|
|
|
|
TLD.StackSize = 0;
|
|
|
|
TLD.StackEntries = 0;
|
|
|
|
TLD.ShadowStack = nullptr;
|
2017-11-21 15:29:21 +08:00
|
|
|
return false;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
}
|
2017-11-21 15:29:21 +08:00
|
|
|
TLD.ShadowStack = reinterpret_cast<StackEntry *>(
|
|
|
|
InternalAlloc(sizeof(StackEntry) * GlobalOptions.MaxStackDepth, nullptr,
|
|
|
|
alignof(StackEntry)));
|
|
|
|
TLD.StackSize = GlobalOptions.MaxStackDepth;
|
|
|
|
TLD.StackEntries = 0;
|
2018-06-05 14:12:42 +08:00
|
|
|
if (Verbosity() >= 2) {
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
static auto UNUSED Once = [] {
|
|
|
|
auto ticks = thresholdTicks();
|
|
|
|
Report("Ticks threshold: %d\n", ticks);
|
|
|
|
return false;
|
|
|
|
}();
|
|
|
|
}
|
2017-11-21 15:29:21 +08:00
|
|
|
return false;
|
|
|
|
}();
|
|
|
|
return TLD;
|
|
|
|
}
|
|
|
|
|
2017-03-15 10:28:00 +08:00
|
|
|
template <class RDTSC>
|
2017-11-21 15:29:21 +08:00
|
|
|
void InMemoryRawLog(int32_t FuncId, XRayEntryType Type,
|
|
|
|
RDTSC ReadTSC) XRAY_NEVER_INSTRUMENT {
|
|
|
|
auto &TLD = getThreadLocalData();
|
2017-10-05 13:45:51 +08:00
|
|
|
int Fd = getGlobalFd();
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
if (Fd == -1)
|
|
|
|
return;
|
|
|
|
|
2017-09-18 14:18:03 +08:00
|
|
|
// Use a simple recursion guard, to handle cases where we're already logging
|
|
|
|
// and for one reason or another, this function gets called again in the same
|
|
|
|
// thread.
|
2018-06-06 14:07:48 +08:00
|
|
|
RecursionGuard G(Guard);
|
|
|
|
if (!G)
|
2017-10-05 13:45:51 +08:00
|
|
|
return;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
|
|
|
|
uint8_t CPU = 0;
|
|
|
|
uint64_t TSC = ReadTSC(CPU);
|
|
|
|
|
|
|
|
switch (Type) {
|
|
|
|
case XRayEntryType::ENTRY:
|
|
|
|
case XRayEntryType::LOG_ARGS_ENTRY: {
|
|
|
|
// Short circuit if we've reached the maximum depth of the stack.
|
|
|
|
if (TLD.StackEntries++ >= TLD.StackSize)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// When we encounter an entry event, we keep track of the TSC and the CPU,
|
|
|
|
// and put it in the stack.
|
|
|
|
StackEntry E;
|
|
|
|
E.FuncId = FuncId;
|
|
|
|
E.CPU = CPU;
|
|
|
|
E.Type = Type;
|
|
|
|
E.TSC = TSC;
|
|
|
|
auto StackEntryPtr = static_cast<char *>(TLD.ShadowStack) +
|
|
|
|
(sizeof(StackEntry) * (TLD.StackEntries - 1));
|
2018-06-05 14:12:42 +08:00
|
|
|
internal_memcpy(StackEntryPtr, &E, sizeof(StackEntry));
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XRayEntryType::EXIT:
|
|
|
|
case XRayEntryType::TAIL: {
|
|
|
|
if (TLD.StackEntries == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (--TLD.StackEntries >= TLD.StackSize)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// When we encounter an exit event, we check whether all the following are
|
|
|
|
// true:
|
|
|
|
//
|
|
|
|
// - The Function ID is the same as the most recent entry in the stack.
|
|
|
|
// - The CPU is the same as the most recent entry in the stack.
|
|
|
|
// - The Delta of the TSCs is less than the threshold amount of time we're
|
|
|
|
// looking to record.
|
|
|
|
//
|
|
|
|
// If all of these conditions are true, we pop the stack and don't write a
|
|
|
|
// record and move the record offset back.
|
|
|
|
StackEntry StackTop;
|
|
|
|
auto StackEntryPtr = static_cast<char *>(TLD.ShadowStack) +
|
|
|
|
(sizeof(StackEntry) * TLD.StackEntries);
|
2018-06-05 14:12:42 +08:00
|
|
|
internal_memcpy(&StackTop, StackEntryPtr, sizeof(StackEntry));
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
if (StackTop.FuncId == FuncId && StackTop.CPU == CPU &&
|
|
|
|
StackTop.TSC < TSC) {
|
|
|
|
auto Delta = TSC - StackTop.TSC;
|
|
|
|
if (Delta < thresholdTicks()) {
|
|
|
|
assert(TLD.BufferOffset > 0);
|
|
|
|
TLD.BufferOffset -= StackTop.Type == XRayEntryType::ENTRY ? 1 : 2;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// Should be unreachable.
|
|
|
|
assert(false && "Unsupported XRayEntryType encountered.");
|
|
|
|
break;
|
|
|
|
}
|
2017-09-18 14:18:03 +08:00
|
|
|
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
// First determine whether the delta between the function's enter record and
|
|
|
|
// the exit record is higher than the threshold.
|
2018-06-05 18:12:58 +08:00
|
|
|
XRayRecord R;
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
R.RecordType = RecordTypes::NORMAL;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
R.CPU = CPU;
|
|
|
|
R.TSC = TSC;
|
|
|
|
R.TId = TLD.TID;
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
R.Type = Type;
|
|
|
|
R.FuncId = FuncId;
|
2018-06-05 18:12:58 +08:00
|
|
|
auto FirstEntry = reinterpret_cast<XRayRecord *>(TLD.InMemoryBuffer);
|
2018-06-05 14:12:42 +08:00
|
|
|
internal_memcpy(FirstEntry + TLD.BufferOffset, &R, sizeof(R));
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
if (++TLD.BufferOffset == TLD.BufferSize) {
|
2018-06-05 14:12:42 +08:00
|
|
|
SpinMutexLock L(&LogMutex);
|
2018-01-19 21:18:40 +08:00
|
|
|
retryingWriteAll(Fd, reinterpret_cast<char *>(FirstEntry),
|
|
|
|
reinterpret_cast<char *>(FirstEntry + TLD.BufferOffset));
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
TLD.BufferOffset = 0;
|
|
|
|
TLD.StackEntries = 0;
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-05 13:45:51 +08:00
|
|
|
template <class RDTSC>
|
2017-11-21 15:29:21 +08:00
|
|
|
void InMemoryRawLogWithArg(int32_t FuncId, XRayEntryType Type, uint64_t Arg1,
|
|
|
|
RDTSC ReadTSC) XRAY_NEVER_INSTRUMENT {
|
|
|
|
auto &TLD = getThreadLocalData();
|
2018-01-19 21:18:40 +08:00
|
|
|
auto FirstEntry =
|
2018-06-05 18:12:58 +08:00
|
|
|
reinterpret_cast<XRayArgPayload *>(TLD.InMemoryBuffer);
|
2017-11-21 15:29:21 +08:00
|
|
|
const auto &BuffLen = TLD.BufferSize;
|
2017-10-05 13:45:51 +08:00
|
|
|
int Fd = getGlobalFd();
|
|
|
|
if (Fd == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// First we check whether there's enough space to write the data consecutively
|
|
|
|
// in the thread-local buffer. If not, we first flush the buffer before
|
|
|
|
// attempting to write the two records that must be consecutive.
|
2018-01-19 21:18:40 +08:00
|
|
|
if (TLD.BufferOffset + 2 > BuffLen) {
|
2018-06-05 14:12:42 +08:00
|
|
|
SpinMutexLock L(&LogMutex);
|
2018-01-19 21:18:40 +08:00
|
|
|
retryingWriteAll(Fd, reinterpret_cast<char *>(FirstEntry),
|
|
|
|
reinterpret_cast<char *>(FirstEntry + TLD.BufferOffset));
|
|
|
|
TLD.BufferOffset = 0;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
TLD.StackEntries = 0;
|
2017-10-05 13:45:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Then we write the "we have an argument" record.
|
2017-11-21 15:29:21 +08:00
|
|
|
InMemoryRawLog(FuncId, Type, ReadTSC);
|
2017-10-05 13:45:51 +08:00
|
|
|
|
2018-06-06 14:07:48 +08:00
|
|
|
RecursionGuard G(Guard);
|
|
|
|
if (!G)
|
2017-10-05 13:45:51 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// And from here on write the arg payload.
|
2018-06-05 18:12:58 +08:00
|
|
|
XRayArgPayload R;
|
2017-10-05 13:45:51 +08:00
|
|
|
R.RecordType = RecordTypes::ARG_PAYLOAD;
|
|
|
|
R.FuncId = FuncId;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
R.TId = TLD.TID;
|
2017-10-05 13:45:51 +08:00
|
|
|
R.Arg = Arg1;
|
2018-06-05 14:12:42 +08:00
|
|
|
internal_memcpy(FirstEntry + TLD.BufferOffset, &R, sizeof(R));
|
2018-01-19 21:18:40 +08:00
|
|
|
if (++TLD.BufferOffset == BuffLen) {
|
2018-06-05 14:12:42 +08:00
|
|
|
SpinMutexLock L(&LogMutex);
|
2018-01-19 21:18:40 +08:00
|
|
|
retryingWriteAll(Fd, reinterpret_cast<char *>(FirstEntry),
|
|
|
|
reinterpret_cast<char *>(FirstEntry + TLD.BufferOffset));
|
|
|
|
TLD.BufferOffset = 0;
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
TLD.StackEntries = 0;
|
2017-10-05 13:45:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
void basicLoggingHandleArg0RealTSC(int32_t FuncId,
|
|
|
|
XRayEntryType Type) XRAY_NEVER_INSTRUMENT {
|
2018-06-05 18:12:58 +08:00
|
|
|
InMemoryRawLog(FuncId, Type, readTSC);
|
2017-03-15 10:28:00 +08:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
void basicLoggingHandleArg0EmulateTSC(int32_t FuncId, XRayEntryType Type)
|
|
|
|
XRAY_NEVER_INSTRUMENT {
|
|
|
|
InMemoryRawLog(FuncId, Type, [](uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
|
2017-03-15 10:28:00 +08:00
|
|
|
timespec TS;
|
|
|
|
int result = clock_gettime(CLOCK_REALTIME, &TS);
|
|
|
|
if (result != 0) {
|
|
|
|
Report("clock_gettimg(2) return %d, errno=%d.", result, int(errno));
|
|
|
|
TS = {0, 0};
|
|
|
|
}
|
|
|
|
CPU = 0;
|
2018-06-05 18:12:58 +08:00
|
|
|
return TS.tv_sec * NanosecondsPerSecond + TS.tv_nsec;
|
2017-03-15 10:28:00 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
void basicLoggingHandleArg1RealTSC(int32_t FuncId, XRayEntryType Type,
|
|
|
|
uint64_t Arg1) XRAY_NEVER_INSTRUMENT {
|
2018-06-05 18:12:58 +08:00
|
|
|
InMemoryRawLogWithArg(FuncId, Type, Arg1, readTSC);
|
2017-10-05 13:45:51 +08:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
void basicLoggingHandleArg1EmulateTSC(int32_t FuncId, XRayEntryType Type,
|
|
|
|
uint64_t Arg1) XRAY_NEVER_INSTRUMENT {
|
|
|
|
InMemoryRawLogWithArg(
|
2017-10-05 13:45:51 +08:00
|
|
|
FuncId, Type, Arg1, [](uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
|
|
|
|
timespec TS;
|
|
|
|
int result = clock_gettime(CLOCK_REALTIME, &TS);
|
|
|
|
if (result != 0) {
|
|
|
|
Report("clock_gettimg(2) return %d, errno=%d.", result, int(errno));
|
|
|
|
TS = {0, 0};
|
|
|
|
}
|
|
|
|
CPU = 0;
|
2018-06-05 18:12:58 +08:00
|
|
|
return TS.tv_sec * NanosecondsPerSecond + TS.tv_nsec;
|
2017-10-05 13:45:51 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
static void TLDDestructor(void *P) XRAY_NEVER_INSTRUMENT {
|
|
|
|
ThreadLocalData &TLD = *reinterpret_cast<ThreadLocalData *>(P);
|
2018-06-05 14:12:42 +08:00
|
|
|
auto ExitGuard = at_scope_exit([&TLD] {
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
// Clean up dynamic resources.
|
|
|
|
if (TLD.InMemoryBuffer)
|
|
|
|
InternalFree(TLD.InMemoryBuffer);
|
|
|
|
if (TLD.ShadowStack)
|
|
|
|
InternalFree(TLD.ShadowStack);
|
2018-06-05 14:12:42 +08:00
|
|
|
if (Verbosity())
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
Report("Cleaned up log for TID: %d\n", TLD.TID);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (TLD.Fd == -1 || TLD.BufferOffset == 0) {
|
2018-06-05 14:12:42 +08:00
|
|
|
if (Verbosity())
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
Report("Skipping buffer for TID: %d; Fd = %d; Offset = %llu\n", TLD.TID,
|
|
|
|
TLD.Fd, TLD.BufferOffset);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2018-06-05 14:12:42 +08:00
|
|
|
SpinMutexLock L(&LogMutex);
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
retryingWriteAll(TLD.Fd, reinterpret_cast<char *>(TLD.InMemoryBuffer),
|
|
|
|
reinterpret_cast<char *>(TLD.InMemoryBuffer) +
|
2018-06-05 18:12:58 +08:00
|
|
|
(sizeof(XRayRecord) * TLD.BufferOffset));
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Because this thread's exit could be the last one trying to write to
|
|
|
|
// the file and that we're not able to close out the file properly, we
|
|
|
|
// sync instead and hope that the pending writes are flushed as the
|
|
|
|
// thread exits.
|
|
|
|
fsync(TLD.Fd);
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
XRayLogInitStatus basicLoggingInit(size_t BufferSize, size_t BufferMax,
|
|
|
|
void *Options,
|
|
|
|
size_t OptionsSize) XRAY_NEVER_INSTRUMENT {
|
|
|
|
uint8_t Expected = 0;
|
2018-06-05 14:12:42 +08:00
|
|
|
if (!atomic_compare_exchange_strong(
|
|
|
|
&BasicInitialized, &Expected, 1, memory_order_acq_rel)) {
|
|
|
|
if (Verbosity())
|
2017-11-21 15:29:21 +08:00
|
|
|
Report("Basic logging already initialized.\n");
|
|
|
|
return XRayLogInitStatus::XRAY_LOG_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
2018-05-04 14:27:53 +08:00
|
|
|
static bool UNUSED Once = [] {
|
|
|
|
pthread_key_create(&PThreadKey, TLDDestructor);
|
|
|
|
return false;
|
|
|
|
}();
|
|
|
|
|
|
|
|
if (BufferSize == 0 && BufferMax == 0 && Options != nullptr) {
|
|
|
|
FlagParser P;
|
|
|
|
BasicFlags F;
|
|
|
|
F.setDefaults();
|
|
|
|
registerXRayBasicFlags(&P, &F);
|
|
|
|
P.ParseString(useCompilerDefinedBasicFlags());
|
|
|
|
auto *EnvOpts = GetEnv("XRAY_BASIC_OPTIONS");
|
|
|
|
if (EnvOpts == nullptr)
|
|
|
|
EnvOpts = "";
|
|
|
|
|
|
|
|
P.ParseString(EnvOpts);
|
|
|
|
|
|
|
|
// If XRAY_BASIC_OPTIONS was not defined, then we use the deprecated options
|
|
|
|
// set through XRAY_OPTIONS instead.
|
|
|
|
if (internal_strlen(EnvOpts) == 0) {
|
|
|
|
F.func_duration_threshold_us =
|
|
|
|
flags()->xray_naive_log_func_duration_threshold_us;
|
|
|
|
F.max_stack_depth = flags()->xray_naive_log_max_stack_depth;
|
|
|
|
F.thread_buffer_size = flags()->xray_naive_log_thread_buffer_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
P.ParseString(static_cast<const char *>(Options));
|
|
|
|
GlobalOptions.ThreadBufferSize = F.thread_buffer_size;
|
|
|
|
GlobalOptions.DurationFilterMicros = F.func_duration_threshold_us;
|
|
|
|
GlobalOptions.MaxStackDepth = F.max_stack_depth;
|
|
|
|
} else if (OptionsSize != sizeof(BasicLoggingOptions)) {
|
2017-11-21 15:29:21 +08:00
|
|
|
Report("Invalid options size, potential ABI mismatch; expected %d got %d",
|
|
|
|
sizeof(BasicLoggingOptions), OptionsSize);
|
|
|
|
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;
|
2018-05-04 14:27:53 +08:00
|
|
|
} else {
|
|
|
|
if (Verbosity())
|
|
|
|
Report("XRay Basic: struct-based init is deprecated, please use "
|
|
|
|
"string-based configuration instead.\n");
|
|
|
|
GlobalOptions = *reinterpret_cast<BasicLoggingOptions *>(Options);
|
2017-11-21 15:29:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static auto UseRealTSC = probeRequiredCPUFeatures();
|
2018-06-05 14:12:42 +08:00
|
|
|
if (!UseRealTSC && Verbosity())
|
2017-03-15 10:28:00 +08:00
|
|
|
Report("WARNING: Required CPU features missing for XRay instrumentation, "
|
|
|
|
"using emulation instead.\n");
|
2017-11-21 15:29:21 +08:00
|
|
|
|
|
|
|
__xray_set_handler_arg1(UseRealTSC ? basicLoggingHandleArg1RealTSC
|
|
|
|
: basicLoggingHandleArg1EmulateTSC);
|
|
|
|
__xray_set_handler(UseRealTSC ? basicLoggingHandleArg0RealTSC
|
|
|
|
: basicLoggingHandleArg0EmulateTSC);
|
|
|
|
__xray_remove_customevent_handler();
|
2018-04-18 05:28:53 +08:00
|
|
|
__xray_remove_typedevent_handler();
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
|
2017-11-21 15:29:21 +08:00
|
|
|
return XRayLogInitStatus::XRAY_LOG_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
XRayLogInitStatus basicLoggingFinalize() XRAY_NEVER_INSTRUMENT {
|
|
|
|
uint8_t Expected = 0;
|
2018-06-05 14:12:42 +08:00
|
|
|
if (!atomic_compare_exchange_strong(
|
|
|
|
&BasicInitialized, &Expected, 0, memory_order_acq_rel) &&
|
|
|
|
Verbosity())
|
2017-11-21 15:29:21 +08:00
|
|
|
Report("Basic logging already finalized.\n");
|
|
|
|
|
|
|
|
// Nothing really to do aside from marking state of the global to be
|
|
|
|
// uninitialized.
|
|
|
|
|
|
|
|
return XRayLogInitStatus::XRAY_LOG_FINALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
XRayLogFlushStatus basicLoggingFlush() XRAY_NEVER_INSTRUMENT {
|
|
|
|
// This really does nothing, since flushing the logs happen at the end of a
|
|
|
|
// thread's lifetime, or when the buffers are full.
|
|
|
|
return XRayLogFlushStatus::XRAY_LOG_FLUSHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a handler that, effectively, does nothing.
|
|
|
|
void basicLoggingHandleArg0Empty(int32_t, XRayEntryType) XRAY_NEVER_INSTRUMENT {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool basicLogDynamicInitializer() XRAY_NEVER_INSTRUMENT {
|
2017-12-05 20:08:56 +08:00
|
|
|
XRayLogImpl Impl{
|
|
|
|
basicLoggingInit,
|
|
|
|
basicLoggingFinalize,
|
|
|
|
basicLoggingHandleArg0Empty,
|
|
|
|
basicLoggingFlush,
|
|
|
|
};
|
|
|
|
auto RegistrationResult = __xray_log_register_mode("xray-basic", Impl);
|
|
|
|
if (RegistrationResult != XRayLogRegisterStatus::XRAY_REGISTRATION_OK &&
|
2018-05-04 14:27:53 +08:00
|
|
|
Verbosity())
|
2017-12-05 20:08:56 +08:00
|
|
|
Report("Cannot register XRay Basic Mode to 'xray-basic'; error = %d\n",
|
|
|
|
RegistrationResult);
|
|
|
|
if (flags()->xray_naive_log ||
|
2018-05-04 14:27:53 +08:00
|
|
|
!internal_strcmp(flags()->xray_mode, "xray-basic")) {
|
|
|
|
auto SelectResult = __xray_log_select_mode("xray-basic");
|
|
|
|
if (SelectResult != XRayLogRegisterStatus::XRAY_REGISTRATION_OK) {
|
|
|
|
if (Verbosity())
|
|
|
|
Report("Failed selecting XRay Basic Mode; error = %d\n", SelectResult);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We initialize the implementation using the data we get from the
|
|
|
|
// XRAY_BASIC_OPTIONS environment variable, at this point of the
|
|
|
|
// implementation.
|
|
|
|
auto *Env = GetEnv("XRAY_BASIC_OPTIONS");
|
|
|
|
auto InitResult =
|
|
|
|
__xray_log_init_mode("xray-basic", Env == nullptr ? "" : Env);
|
|
|
|
if (InitResult != XRayLogInitStatus::XRAY_LOG_INITIALIZED) {
|
|
|
|
if (Verbosity())
|
|
|
|
Report("Failed initializing XRay Basic Mode; error = %d\n", InitResult);
|
|
|
|
return false;
|
|
|
|
}
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
static auto UNUSED Once = [] {
|
|
|
|
static auto UNUSED &TLD = getThreadLocalData();
|
2018-06-05 14:12:42 +08:00
|
|
|
Atexit(+[] { TLDDestructor(&TLD); });
|
[XRay][compiler-rt] Implement XRay Basic Mode Filtering
Summary:
This change implements the basic mode filtering similar to what we do in
FDR mode. The implementation is slightly simpler in basic-mode filtering
because we have less details to remember, but the idea is the same. At a
high level, we do the following to decide when to filter function call
records:
- We maintain a per-thread "shadow stack" which keeps track of the
XRay instrumented functions we've encountered in a thread's
execution.
- We push an entry onto the stack when we enter an XRay instrumented
function, and note the CPU, TSC, and type of entry (whether we have
payload or not when entering).
- When we encounter an exit event, we determine whether the function
being exited is the same function we've entered recently, was
executing in the same CPU, and the delta of the recent TSC and the
recorded TSC at the top of the stack is less than the equivalent
amount of microseconds we're configured to ignore -- then we un-wind
the record offset an appropriate number of times (so we can
overwrite the records later).
We also support limiting the stack depth of the recorded functions,
so that we don't arbitrarily write deep function call stacks.
Reviewers: eizan, pelikan, kpw, dblaikie
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40828
llvm-svn: 319762
2017-12-05 20:21:14 +08:00
|
|
|
return false;
|
|
|
|
}();
|
2017-10-05 13:45:51 +08:00
|
|
|
}
|
[compiler-rt][XRay] Initial per-thread inmemory logging implementation
Depends on D21612 which implements the building blocks for the compiler-rt
implementation of the XRay runtime. We use a naive in-memory log of fixed-size
entries that get written out to a log file when the buffers are full, and when
the thread exits.
This implementation lays some foundations on to allowing for more complex XRay
records to be written to the log in subsequent changes. It also defines the format
that the function call accounting tool in D21987 will start building upon.
Once D21987 lands, we should be able to start defining more tests using that tool
once the function call accounting tool becomes part of the llvm distribution.
Reviewers: echristo, kcc, rnk, eugenis, majnemer, rSerge
Subscribers: sdardis, rSerge, dberris, tberghammer, danalbert, srhines, majnemer, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D21982
llvm-svn: 279805
2016-08-26 14:39:33 +08:00
|
|
|
return true;
|
2017-11-21 15:29:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace __xray
|
|
|
|
|
|
|
|
static auto UNUSED Unused = __xray::basicLogDynamicInitializer();
|