]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | //===-- xray_log_interface.cc ---------------------------------------------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file is a part of XRay, a function call tracing system. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | #include "xray/xray_log_interface.h" | |
14 | ||
15 | #include "sanitizer_common/sanitizer_allocator_internal.h" | |
16 | #include "sanitizer_common/sanitizer_atomic.h" | |
17 | #include "sanitizer_common/sanitizer_mutex.h" | |
18 | #include "xray/xray_interface.h" | |
19 | #include "xray_defs.h" | |
20 | ||
21 | __sanitizer::SpinMutex XRayImplMutex; | |
22 | XRayLogImpl CurrentXRayImpl{nullptr, nullptr, nullptr, nullptr}; | |
23 | XRayLogImpl *GlobalXRayImpl = nullptr; | |
24 | ||
25 | // We use a linked list of Mode to XRayLogImpl mappings. This is a linked list | |
26 | // when it should be a map because we're avoiding having to depend on C++ | |
27 | // standard library data structures at this level of the implementation. | |
28 | struct ModeImpl { | |
29 | ModeImpl *Next; | |
30 | const char *Mode; | |
31 | XRayLogImpl Impl; | |
32 | }; | |
33 | ||
34 | ModeImpl SentinelModeImpl{ | |
35 | nullptr, nullptr, {nullptr, nullptr, nullptr, nullptr}}; | |
36 | ModeImpl *ModeImpls = &SentinelModeImpl; | |
37 | ||
38 | XRayLogRegisterStatus | |
39 | __xray_log_register_mode(const char *Mode, | |
40 | XRayLogImpl Impl) XRAY_NEVER_INSTRUMENT { | |
41 | if (Impl.flush_log == nullptr || Impl.handle_arg0 == nullptr || | |
42 | Impl.log_finalize == nullptr || Impl.log_init == nullptr) | |
43 | return XRayLogRegisterStatus::XRAY_INCOMPLETE_IMPL; | |
44 | ||
45 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
46 | // First, look for whether the mode already has a registered implementation. | |
47 | for (ModeImpl *it = ModeImpls; it != &SentinelModeImpl; it = it->Next) { | |
48 | if (!__sanitizer::internal_strcmp(Mode, it->Mode)) | |
49 | return XRayLogRegisterStatus::XRAY_DUPLICATE_MODE; | |
50 | } | |
51 | auto *NewModeImpl = | |
52 | static_cast<ModeImpl *>(__sanitizer::InternalAlloc(sizeof(ModeImpl))); | |
53 | NewModeImpl->Next = ModeImpls; | |
54 | NewModeImpl->Mode = __sanitizer::internal_strdup(Mode); | |
55 | NewModeImpl->Impl = Impl; | |
56 | ModeImpls = NewModeImpl; | |
57 | return XRayLogRegisterStatus::XRAY_REGISTRATION_OK; | |
58 | } | |
59 | ||
60 | XRayLogRegisterStatus | |
61 | __xray_log_select_mode(const char *Mode) XRAY_NEVER_INSTRUMENT { | |
62 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
63 | for (ModeImpl *it = ModeImpls; it != &SentinelModeImpl; it = it->Next) { | |
64 | if (!__sanitizer::internal_strcmp(Mode, it->Mode)) { | |
65 | CurrentXRayImpl = it->Impl; | |
66 | GlobalXRayImpl = &CurrentXRayImpl; | |
67 | __xray_set_handler(it->Impl.handle_arg0); | |
68 | return XRayLogRegisterStatus::XRAY_REGISTRATION_OK; | |
69 | } | |
70 | } | |
71 | return XRayLogRegisterStatus::XRAY_MODE_NOT_FOUND; | |
72 | } | |
73 | ||
74 | void __xray_set_log_impl(XRayLogImpl Impl) XRAY_NEVER_INSTRUMENT { | |
75 | if (Impl.log_init == nullptr || Impl.log_finalize == nullptr || | |
76 | Impl.handle_arg0 == nullptr || Impl.flush_log == nullptr) { | |
77 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
78 | GlobalXRayImpl = nullptr; | |
79 | __xray_remove_handler(); | |
80 | __xray_remove_handler_arg1(); | |
81 | return; | |
82 | } | |
83 | ||
84 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
85 | CurrentXRayImpl = Impl; | |
86 | GlobalXRayImpl = &CurrentXRayImpl; | |
87 | __xray_set_handler(Impl.handle_arg0); | |
88 | } | |
89 | ||
90 | void __xray_remove_log_impl() XRAY_NEVER_INSTRUMENT { | |
91 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
92 | GlobalXRayImpl = nullptr; | |
93 | __xray_remove_handler(); | |
94 | __xray_remove_handler_arg1(); | |
95 | } | |
96 | ||
97 | XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers, | |
98 | void *Args, | |
99 | size_t ArgsSize) XRAY_NEVER_INSTRUMENT { | |
100 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
101 | if (!GlobalXRayImpl) | |
102 | return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED; | |
103 | return GlobalXRayImpl->log_init(BufferSize, MaxBuffers, Args, ArgsSize); | |
104 | } | |
105 | ||
106 | XRayLogInitStatus __xray_log_finalize() XRAY_NEVER_INSTRUMENT { | |
107 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
108 | if (!GlobalXRayImpl) | |
109 | return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED; | |
110 | return GlobalXRayImpl->log_finalize(); | |
111 | } | |
112 | ||
113 | XRayLogFlushStatus __xray_log_flushLog() XRAY_NEVER_INSTRUMENT { | |
114 | __sanitizer::SpinMutexLock Guard(&XRayImplMutex); | |
115 | if (!GlobalXRayImpl) | |
116 | return XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING; | |
117 | return GlobalXRayImpl->flush_log(); | |
118 | } |