Skip to content

Commit

Permalink
[XRay][compiler-rt] Remove use of std::mutex and std::shared_ptr from…
Browse files Browse the repository at this point in the history
… global scope.

Summary:
This change attempts to remove all the dependencies we have on
std::mutex and any std::shared_ptr construction in global variables. We
instead use raw pointers to these objects, and construct them on the
heap. In cases where it's possible, we lazily initialize these pointers.

While we do not have a replacement for std::shared_ptr yet in
compiler-rt, we use this work-around to avoid having to statically
initialize the objects as globals. Subsequent changes should allow us to
completely remove our dependency on std::shared_ptr and instead have our
own implementation of the std::shared_ptr and std::weak_ptr semantics
(or completely rewrite the implementaton to not need these
standard-library provided abstractions).

Reviewers: dblaikie, kpw, pelikan

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D36078

llvm-svn: 309792
  • Loading branch information
deanberris committed Aug 2, 2017
1 parent c2f73b7 commit 9952d95
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 29 deletions.
2 changes: 2 additions & 0 deletions compiler-rt/include/xray/xray_records.h
Expand Up @@ -17,6 +17,8 @@
#ifndef XRAY_XRAY_RECORDS_H
#define XRAY_XRAY_RECORDS_H

#include <cstdint>

namespace __xray {

enum FileTypes {
Expand Down
20 changes: 13 additions & 7 deletions compiler-rt/lib/xray/xray_fdr_logging.cc
Expand Up @@ -39,7 +39,10 @@
namespace __xray {

// Global BufferQueue.
std::shared_ptr<BufferQueue> BQ;
// NOTE: This is a pointer to avoid having to do atomic operations at
// initialization time. This is OK to leak as there will only be one bufferqueue
// for the runtime, initialized once through the fdrInit(...) sequence.
std::shared_ptr<BufferQueue>* BQ = nullptr;

__sanitizer::atomic_sint32_t LogFlushStatus = {
XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING};
Expand All @@ -64,7 +67,7 @@ XRayLogFlushStatus fdrLoggingFlush() XRAY_NEVER_INSTRUMENT {
// Make a copy of the BufferQueue pointer to prevent other threads that may be
// resetting it from blowing away the queue prematurely while we're dealing
// with it.
auto LocalBQ = BQ;
auto LocalBQ = *BQ;

// We write out the file in the following format:
//
Expand Down Expand Up @@ -129,7 +132,7 @@ XRayLogInitStatus fdrLoggingFinalize() XRAY_NEVER_INSTRUMENT {

// Do special things to make the log finalize itself, and not allow any more
// operations to be performed until re-initialized.
BQ->finalize();
(*BQ)->finalize();

__sanitizer::atomic_store(&LoggingStatus,
XRayLogInitStatus::XRAY_LOG_FINALIZED,
Expand All @@ -146,7 +149,7 @@ XRayLogInitStatus fdrLoggingReset() XRAY_NEVER_INSTRUMENT {
return static_cast<XRayLogInitStatus>(CurrentStatus);

// Release the in-memory buffer queue.
BQ.reset();
BQ->reset();

// Spin until the flushing status is flushed.
s32 CurrentFlushingStatus = XRayLogFlushStatus::XRAY_LOG_FLUSHED;
Expand Down Expand Up @@ -195,7 +198,7 @@ void fdrLoggingHandleArg0(int32_t FuncId,
auto TSC_CPU = getTimestamp();
__xray_fdr_internal::processFunctionHook(FuncId, Entry, std::get<0>(TSC_CPU),
std::get<1>(TSC_CPU), clock_gettime,
LoggingStatus, BQ);
LoggingStatus, *BQ);
}

void fdrLoggingHandleCustomEvent(void *Event,
Expand All @@ -220,7 +223,7 @@ void fdrLoggingHandleCustomEvent(void *Event,
(void)Once;
}
int32_t ReducedEventSize = static_cast<int32_t>(EventSize);
if (!isLogInitializedAndReady(LocalBQ, TSC, CPU, clock_gettime))
if (!isLogInitializedAndReady(*LocalBQ, TSC, CPU, clock_gettime))
return;

// Here we need to prepare the log to handle:
Expand Down Expand Up @@ -268,7 +271,10 @@ XRayLogInitStatus fdrLoggingInit(std::size_t BufferSize, std::size_t BufferMax,
}

bool Success = false;
BQ = std::make_shared<BufferQueue>(BufferSize, BufferMax, Success);
if (BQ == nullptr)
BQ = new std::shared_ptr<BufferQueue>();

*BQ = std::make_shared<BufferQueue>(BufferSize, BufferMax, Success);
if (!Success) {
Report("BufferQueue init failed.\n");
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;
Expand Down
35 changes: 18 additions & 17 deletions compiler-rt/lib/xray/xray_fdr_logging_impl.h
Expand Up @@ -169,8 +169,9 @@ class ThreadExitBufferCleanup {
// Make sure a thread that's ever called handleArg0 has a thread-local
// live reference to the buffer queue for this particular instance of
// FDRLogging, and that we're going to clean it up when the thread exits.
thread_local std::shared_ptr<BufferQueue> LocalBQ = nullptr;
thread_local ThreadExitBufferCleanup Cleanup(LocalBQ, Buffer);
thread_local std::shared_ptr<BufferQueue>* LocalBQ =
new std::shared_ptr<BufferQueue>();
thread_local ThreadExitBufferCleanup Cleanup(*LocalBQ, Buffer);

class RecursionGuard {
bool &Running;
Expand Down Expand Up @@ -451,8 +452,8 @@ static void rewindRecentCall(uint64_t TSC, uint64_t &LastTSC,
}
}

inline bool releaseThreadLocalBuffer(BufferQueue *BQ) {
auto EC = BQ->releaseBuffer(Buffer);
inline bool releaseThreadLocalBuffer(BufferQueue &BQArg) {
auto EC = BQArg.releaseBuffer(Buffer);
if (EC != BufferQueue::ErrorCode::Ok) {
Report("Failed to release buffer at %p; error=%s\n", Buffer.Buffer,
BufferQueue::getErrorString(EC));
Expand All @@ -467,9 +468,9 @@ inline bool prepareBuffer(int (*wall_clock_reader)(clockid_t,
char *BufferStart = static_cast<char *>(Buffer.Buffer);
if ((RecordPtr + MaxSize) > (BufferStart + Buffer.Size - MetadataRecSize)) {
writeEOBMetadata();
if (!releaseThreadLocalBuffer(LocalBQ.get()))
if (!releaseThreadLocalBuffer(**LocalBQ))
return false;
auto EC = LocalBQ->getBuffer(Buffer);
auto EC = (*LocalBQ)->getBuffer(Buffer);
if (EC != BufferQueue::ErrorCode::Ok) {
Report("Failed to acquire a buffer; error=%s\n",
BufferQueue::getErrorString(EC));
Expand All @@ -481,7 +482,7 @@ inline bool prepareBuffer(int (*wall_clock_reader)(clockid_t,
}

inline bool isLogInitializedAndReady(
std::shared_ptr<BufferQueue> &LocalBQ, uint64_t TSC, unsigned char CPU,
std::shared_ptr<BufferQueue> &LBQ, uint64_t TSC, unsigned char CPU,
int (*wall_clock_reader)(clockid_t,
struct timespec *)) XRAY_NEVER_INSTRUMENT {
// Bail out right away if logging is not initialized yet.
Expand All @@ -493,24 +494,24 @@ inline bool isLogInitializedAndReady(
(Status == XRayLogInitStatus::XRAY_LOG_FINALIZING ||
Status == XRayLogInitStatus::XRAY_LOG_FINALIZED)) {
writeEOBMetadata();
if (!releaseThreadLocalBuffer(LocalBQ.get()))
if (!releaseThreadLocalBuffer(*LBQ))
return false;
RecordPtr = nullptr;
LocalBQ = nullptr;
LBQ = nullptr;
return false;
}
return false;
}

if (!loggingInitialized(LoggingStatus) || LocalBQ->finalizing()) {
if (!loggingInitialized(LoggingStatus) || LBQ->finalizing()) {
writeEOBMetadata();
if (!releaseThreadLocalBuffer(LocalBQ.get()))
if (!releaseThreadLocalBuffer(*LBQ))
return false;
RecordPtr = nullptr;
}

if (Buffer.Buffer == nullptr) {
auto EC = LocalBQ->getBuffer(Buffer);
auto EC = LBQ->getBuffer(Buffer);
if (EC != BufferQueue::ErrorCode::Ok) {
auto LS = __sanitizer::atomic_load(&LoggingStatus,
__sanitizer::memory_order_acquire);
Expand Down Expand Up @@ -538,7 +539,7 @@ inline void endBufferIfFull() XRAY_NEVER_INSTRUMENT {
auto BufferStart = static_cast<char *>(Buffer.Buffer);
if ((RecordPtr + MetadataRecSize) - BufferStart == MetadataRecSize) {
writeEOBMetadata();
if (!releaseThreadLocalBuffer(LocalBQ.get()))
if (!releaseThreadLocalBuffer(**LocalBQ))
return;
RecordPtr = nullptr;
}
Expand All @@ -563,10 +564,10 @@ inline void processFunctionHook(

// In case the reference has been cleaned up before, we make sure we
// initialize it to the provided BufferQueue.
if (LocalBQ == nullptr)
LocalBQ = BQ;
if ((*LocalBQ) == nullptr)
*LocalBQ = BQ;

if (!isLogInitializedAndReady(LocalBQ, TSC, CPU, wall_clock_reader))
if (!isLogInitializedAndReady(*LocalBQ, TSC, CPU, wall_clock_reader))
return;

// Before we go setting up writing new function entries, we need to be really
Expand Down Expand Up @@ -606,7 +607,7 @@ inline void processFunctionHook(
// Buffer, set it up properly before doing any further writing.
//
if (!prepareBuffer(wall_clock_reader, FunctionRecSize + MetadataRecSize)) {
LocalBQ = nullptr;
*LocalBQ = nullptr;
return;
}

Expand Down
10 changes: 5 additions & 5 deletions compiler-rt/lib/xray/xray_inmemory_log.cc
Expand Up @@ -16,12 +16,12 @@
//===----------------------------------------------------------------------===//

#include <cassert>
#include <errno.h>
#include <fcntl.h>
#include <mutex>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <thread>
#include <time.h>
#include <unistd.h>

#include "sanitizer_common/sanitizer_libc.h"
Expand All @@ -43,7 +43,7 @@ void __xray_InMemoryRawLog(int32_t FuncId,

namespace __xray {

std::mutex LogMutex;
__sanitizer::SpinMutex LogMutex;

class ThreadExitFlusher {
int Fd;
Expand All @@ -58,7 +58,7 @@ class ThreadExitFlusher {
Offset(Offset) {}

~ThreadExitFlusher() XRAY_NEVER_INSTRUMENT {
std::lock_guard<std::mutex> L(LogMutex);
__sanitizer::SpinMutexLock L(&LogMutex);
if (Fd > 0 && Start != nullptr) {
retryingWriteAll(Fd, reinterpret_cast<char *>(Start),
reinterpret_cast<char *>(Start + Offset));
Expand Down Expand Up @@ -127,7 +127,7 @@ void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type,
R.FuncId = FuncId;
++Offset;
if (Offset == BuffLen) {
std::lock_guard<std::mutex> L(LogMutex);
__sanitizer::SpinMutexLock L(&LogMutex);
auto RecordBuffer = reinterpret_cast<__xray::XRayRecord *>(InMemoryBuffer);
retryingWriteAll(Fd, reinterpret_cast<char *>(RecordBuffer),
reinterpret_cast<char *>(RecordBuffer + Offset));
Expand Down

0 comments on commit 9952d95

Please sign in to comment.