003 File Manager
Current Path:
/usr/src/contrib/llvm-project/compiler-rt/lib/xray
usr
/
src
/
contrib
/
llvm-project
/
compiler-rt
/
lib
/
xray
/
📁
..
📄
weak_symbols.txt
(88 B)
📄
xray_AArch64.cpp
(4.62 KB)
📄
xray_allocator.h
(9.33 KB)
📄
xray_always_instrument.txt
(255 B)
📄
xray_arm.cpp
(5.87 KB)
📄
xray_basic_flags.cpp
(1.52 KB)
📄
xray_basic_flags.h
(1.18 KB)
📄
xray_basic_flags.inc
(1011 B)
📄
xray_basic_logging.cpp
(17.59 KB)
📄
xray_basic_logging.h
(1.68 KB)
📄
xray_buffer_queue.cpp
(7.35 KB)
📄
xray_buffer_queue.h
(8.79 KB)
📄
xray_defs.h
(967 B)
📄
xray_fdr_controller.h
(11.79 KB)
📄
xray_fdr_flags.cpp
(1.47 KB)
📄
xray_fdr_flags.h
(1.2 KB)
📄
xray_fdr_flags.inc
(1.28 KB)
📄
xray_fdr_log_records.h
(2.5 KB)
📄
xray_fdr_log_writer.h
(8.72 KB)
📄
xray_fdr_logging.cpp
(27.62 KB)
📄
xray_fdr_logging.h
(1.53 KB)
📄
xray_flags.cpp
(2.76 KB)
📄
xray_flags.h
(1.12 KB)
📄
xray_flags.inc
(2.29 KB)
📄
xray_function_call_trie.h
(22.36 KB)
📄
xray_init.cpp
(4.6 KB)
📄
xray_interface.cpp
(16.43 KB)
📄
xray_interface_internal.h
(3.2 KB)
📄
xray_log_interface.cpp
(7.53 KB)
📄
xray_mips.cpp
(7.16 KB)
📄
xray_mips64.cpp
(7.66 KB)
📄
xray_never_instrument.txt
(282 B)
📄
xray_powerpc64.cpp
(3.63 KB)
📄
xray_powerpc64.inc
(1019 B)
📄
xray_profile_collector.cpp
(14.06 KB)
📄
xray_profile_collector.h
(2.73 KB)
📄
xray_profiling.cpp
(17.55 KB)
📄
xray_profiling_flags.cpp
(1.34 KB)
📄
xray_profiling_flags.h
(1.17 KB)
📄
xray_profiling_flags.inc
(1.4 KB)
📄
xray_recursion_guard.h
(1.8 KB)
📄
xray_segmented_array.h
(21.22 KB)
📄
xray_trampoline_AArch64.S
(6.1 KB)
📄
xray_trampoline_arm.S
(3.85 KB)
📄
xray_trampoline_mips.S
(2.67 KB)
📄
xray_trampoline_mips64.S
(3.47 KB)
📄
xray_trampoline_powerpc64.cpp
(420 B)
📄
xray_trampoline_powerpc64_asm.S
(3.91 KB)
📄
xray_trampoline_x86_64.S
(7.06 KB)
📄
xray_tsc.h
(2.75 KB)
📄
xray_utils.cpp
(6.04 KB)
📄
xray_utils.h
(2.18 KB)
📄
xray_x86_64.cpp
(11.73 KB)
📄
xray_x86_64.inc
(997 B)
Editing: xray_fdr_controller.h
//===-- xray_fdr_controller.h ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is a part of XRay, a function call tracing system. // //===----------------------------------------------------------------------===// #ifndef COMPILER_RT_LIB_XRAY_XRAY_FDR_CONTROLLER_H_ #define COMPILER_RT_LIB_XRAY_XRAY_FDR_CONTROLLER_H_ #include <limits> #include <time.h> #include "xray/xray_interface.h" #include "xray/xray_records.h" #include "xray_buffer_queue.h" #include "xray_fdr_log_writer.h" namespace __xray { template <size_t Version = 5> class FDRController { BufferQueue *BQ; BufferQueue::Buffer &B; FDRLogWriter &W; int (*WallClockReader)(clockid_t, struct timespec *) = 0; uint64_t CycleThreshold = 0; uint64_t LastFunctionEntryTSC = 0; uint64_t LatestTSC = 0; uint16_t LatestCPU = 0; tid_t TId = 0; pid_t PId = 0; bool First = true; uint32_t UndoableFunctionEnters = 0; uint32_t UndoableTailExits = 0; bool finalized() const XRAY_NEVER_INSTRUMENT { return BQ == nullptr || BQ->finalizing(); } bool hasSpace(size_t S) XRAY_NEVER_INSTRUMENT { return B.Data != nullptr && B.Generation == BQ->generation() && W.getNextRecord() + S <= reinterpret_cast<char *>(B.Data) + B.Size; } constexpr int32_t mask(int32_t FuncId) const XRAY_NEVER_INSTRUMENT { return FuncId & ((1 << 29) - 1); } bool getNewBuffer() XRAY_NEVER_INSTRUMENT { if (BQ->getBuffer(B) != BufferQueue::ErrorCode::Ok) return false; W.resetRecord(); DCHECK_EQ(W.getNextRecord(), B.Data); LatestTSC = 0; LatestCPU = 0; First = true; UndoableFunctionEnters = 0; UndoableTailExits = 0; atomic_store(B.Extents, 0, memory_order_release); return true; } bool setupNewBuffer() XRAY_NEVER_INSTRUMENT { if (finalized()) return false; DCHECK(hasSpace(sizeof(MetadataRecord) * 3)); TId = GetTid(); PId = internal_getpid(); struct timespec TS { 0, 0 }; WallClockReader(CLOCK_MONOTONIC, &TS); MetadataRecord Metadata[] = { // Write out a MetadataRecord to signify that this is the start of a new // buffer, associated with a particular thread, with a new CPU. For the // data, we have 15 bytes to squeeze as much information as we can. At // this point we only write down the following bytes: // - Thread ID (tid_t, cast to 4 bytes type due to Darwin being 8 // bytes) createMetadataRecord<MetadataRecord::RecordKinds::NewBuffer>( static_cast<int32_t>(TId)), // Also write the WalltimeMarker record. We only really need microsecond // precision here, and enforce across platforms that we need 64-bit // seconds and 32-bit microseconds encoded in the Metadata record. createMetadataRecord<MetadataRecord::RecordKinds::WalltimeMarker>( static_cast<int64_t>(TS.tv_sec), static_cast<int32_t>(TS.tv_nsec / 1000)), // Also write the Pid record. createMetadataRecord<MetadataRecord::RecordKinds::Pid>( static_cast<int32_t>(PId)), }; if (finalized()) return false; return W.writeMetadataRecords(Metadata); } bool prepareBuffer(size_t S) XRAY_NEVER_INSTRUMENT { if (finalized()) return returnBuffer(); if (UNLIKELY(!hasSpace(S))) { if (!returnBuffer()) return false; if (!getNewBuffer()) return false; if (!setupNewBuffer()) return false; } if (First) { First = false; W.resetRecord(); atomic_store(B.Extents, 0, memory_order_release); return setupNewBuffer(); } return true; } bool returnBuffer() XRAY_NEVER_INSTRUMENT { if (BQ == nullptr) return false; First = true; if (finalized()) { BQ->releaseBuffer(B); // ignore result. return false; } return BQ->releaseBuffer(B) == BufferQueue::ErrorCode::Ok; } enum class PreambleResult { NoChange, WroteMetadata, InvalidBuffer }; PreambleResult recordPreamble(uint64_t TSC, uint16_t CPU) XRAY_NEVER_INSTRUMENT { if (UNLIKELY(LatestCPU != CPU || LatestTSC == 0)) { // We update our internal tracking state for the Latest TSC and CPU we've // seen, then write out the appropriate metadata and function records. LatestTSC = TSC; LatestCPU = CPU; if (B.Generation != BQ->generation()) return PreambleResult::InvalidBuffer; W.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>(CPU, TSC); return PreambleResult::WroteMetadata; } DCHECK_EQ(LatestCPU, CPU); if (UNLIKELY(LatestTSC > TSC || TSC - LatestTSC > uint64_t{std::numeric_limits<int32_t>::max()})) { // Either the TSC has wrapped around from the last TSC we've seen or the // delta is too large to fit in a 32-bit signed integer, so we write a // wrap-around record. LatestTSC = TSC; if (B.Generation != BQ->generation()) return PreambleResult::InvalidBuffer; W.writeMetadata<MetadataRecord::RecordKinds::TSCWrap>(TSC); return PreambleResult::WroteMetadata; } return PreambleResult::NoChange; } bool rewindRecords(int32_t FuncId, uint64_t TSC, uint16_t CPU) XRAY_NEVER_INSTRUMENT { // Undo one enter record, because at this point we are either at the state // of: // - We are exiting a function that we recently entered. // - We are exiting a function that was the result of a sequence of tail // exits, and we can check whether the tail exits can be re-wound. // FunctionRecord F; W.undoWrites(sizeof(FunctionRecord)); if (B.Generation != BQ->generation()) return false; internal_memcpy(&F, W.getNextRecord(), sizeof(FunctionRecord)); DCHECK(F.RecordKind == uint8_t(FunctionRecord::RecordKinds::FunctionEnter) && "Expected to find function entry recording when rewinding."); DCHECK_EQ(F.FuncId, FuncId & ~(0x0F << 28)); LatestTSC -= F.TSCDelta; if (--UndoableFunctionEnters != 0) { LastFunctionEntryTSC -= F.TSCDelta; return true; } LastFunctionEntryTSC = 0; auto RewindingTSC = LatestTSC; auto RewindingRecordPtr = W.getNextRecord() - sizeof(FunctionRecord); while (UndoableTailExits) { if (B.Generation != BQ->generation()) return false; internal_memcpy(&F, RewindingRecordPtr, sizeof(FunctionRecord)); DCHECK_EQ(F.RecordKind, uint8_t(FunctionRecord::RecordKinds::FunctionTailExit)); RewindingTSC -= F.TSCDelta; RewindingRecordPtr -= sizeof(FunctionRecord); if (B.Generation != BQ->generation()) return false; internal_memcpy(&F, RewindingRecordPtr, sizeof(FunctionRecord)); // This tail call exceeded the threshold duration. It will not be erased. if ((TSC - RewindingTSC) >= CycleThreshold) { UndoableTailExits = 0; return true; } --UndoableTailExits; W.undoWrites(sizeof(FunctionRecord) * 2); LatestTSC = RewindingTSC; } return true; } public: template <class WallClockFunc> FDRController(BufferQueue *BQ, BufferQueue::Buffer &B, FDRLogWriter &W, WallClockFunc R, uint64_t C) XRAY_NEVER_INSTRUMENT : BQ(BQ), B(B), W(W), WallClockReader(R), CycleThreshold(C) {} bool functionEnter(int32_t FuncId, uint64_t TSC, uint16_t CPU) XRAY_NEVER_INSTRUMENT { if (finalized() || !prepareBuffer(sizeof(MetadataRecord) + sizeof(FunctionRecord))) return returnBuffer(); auto PreambleStatus = recordPreamble(TSC, CPU); if (PreambleStatus == PreambleResult::InvalidBuffer) return returnBuffer(); if (PreambleStatus == PreambleResult::WroteMetadata) { UndoableFunctionEnters = 1; UndoableTailExits = 0; } else { ++UndoableFunctionEnters; } auto Delta = TSC - LatestTSC; LastFunctionEntryTSC = TSC; LatestTSC = TSC; return W.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, mask(FuncId), Delta); } bool functionTailExit(int32_t FuncId, uint64_t TSC, uint16_t CPU) XRAY_NEVER_INSTRUMENT { if (finalized()) return returnBuffer(); if (!prepareBuffer(sizeof(MetadataRecord) + sizeof(FunctionRecord))) return returnBuffer(); auto PreambleStatus = recordPreamble(TSC, CPU); if (PreambleStatus == PreambleResult::InvalidBuffer) return returnBuffer(); if (PreambleStatus == PreambleResult::NoChange && UndoableFunctionEnters != 0 && TSC - LastFunctionEntryTSC < CycleThreshold) return rewindRecords(FuncId, TSC, CPU); UndoableTailExits = UndoableFunctionEnters ? UndoableTailExits + 1 : 0; UndoableFunctionEnters = 0; auto Delta = TSC - LatestTSC; LatestTSC = TSC; return W.writeFunction(FDRLogWriter::FunctionRecordKind::TailExit, mask(FuncId), Delta); } bool functionEnterArg(int32_t FuncId, uint64_t TSC, uint16_t CPU, uint64_t Arg) XRAY_NEVER_INSTRUMENT { if (finalized() || !prepareBuffer((2 * sizeof(MetadataRecord)) + sizeof(FunctionRecord)) || recordPreamble(TSC, CPU) == PreambleResult::InvalidBuffer) return returnBuffer(); auto Delta = TSC - LatestTSC; LatestTSC = TSC; LastFunctionEntryTSC = 0; UndoableFunctionEnters = 0; UndoableTailExits = 0; return W.writeFunctionWithArg(FDRLogWriter::FunctionRecordKind::EnterArg, mask(FuncId), Delta, Arg); } bool functionExit(int32_t FuncId, uint64_t TSC, uint16_t CPU) XRAY_NEVER_INSTRUMENT { if (finalized() || !prepareBuffer(sizeof(MetadataRecord) + sizeof(FunctionRecord))) return returnBuffer(); auto PreambleStatus = recordPreamble(TSC, CPU); if (PreambleStatus == PreambleResult::InvalidBuffer) return returnBuffer(); if (PreambleStatus == PreambleResult::NoChange && UndoableFunctionEnters != 0 && TSC - LastFunctionEntryTSC < CycleThreshold) return rewindRecords(FuncId, TSC, CPU); auto Delta = TSC - LatestTSC; LatestTSC = TSC; UndoableFunctionEnters = 0; UndoableTailExits = 0; return W.writeFunction(FDRLogWriter::FunctionRecordKind::Exit, mask(FuncId), Delta); } bool customEvent(uint64_t TSC, uint16_t CPU, const void *Event, int32_t EventSize) XRAY_NEVER_INSTRUMENT { if (finalized() || !prepareBuffer((2 * sizeof(MetadataRecord)) + EventSize) || recordPreamble(TSC, CPU) == PreambleResult::InvalidBuffer) return returnBuffer(); auto Delta = TSC - LatestTSC; LatestTSC = TSC; UndoableFunctionEnters = 0; UndoableTailExits = 0; return W.writeCustomEvent(Delta, Event, EventSize); } bool typedEvent(uint64_t TSC, uint16_t CPU, uint16_t EventType, const void *Event, int32_t EventSize) XRAY_NEVER_INSTRUMENT { if (finalized() || !prepareBuffer((2 * sizeof(MetadataRecord)) + EventSize) || recordPreamble(TSC, CPU) == PreambleResult::InvalidBuffer) return returnBuffer(); auto Delta = TSC - LatestTSC; LatestTSC = TSC; UndoableFunctionEnters = 0; UndoableTailExits = 0; return W.writeTypedEvent(Delta, EventType, Event, EventSize); } bool flush() XRAY_NEVER_INSTRUMENT { if (finalized()) { returnBuffer(); // ignore result. return true; } return returnBuffer(); } }; } // namespace __xray #endif // COMPILER-RT_LIB_XRAY_XRAY_FDR_CONTROLLER_H_
Upload File
Create Folder