BaseProfilerUtils.h (7551B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef BaseProfilerUtils_h 8 #define BaseProfilerUtils_h 9 10 // This header contains most process- and thread-related functions. 11 // It is safe to include unconditionally. 12 13 // --------------------------------------------- WASI process & thread ids 14 #if defined(__wasi__) 15 16 namespace mozilla::baseprofiler::detail { 17 using ProcessIdType = unsigned; 18 using ThreadIdType = unsigned; 19 } // namespace mozilla::baseprofiler::detail 20 21 // --------------------------------------------- Windows process & thread ids 22 #elif defined(XP_WIN) 23 24 namespace mozilla::baseprofiler::detail { 25 using ProcessIdType = int; 26 using ThreadIdType = unsigned long; 27 } // namespace mozilla::baseprofiler::detail 28 29 // --------------------------------------------- Non-Windows process id 30 #else 31 // All non-Windows platforms are assumed to be POSIX, which has getpid(). 32 33 # include <unistd.h> 34 namespace mozilla::baseprofiler::detail { 35 using ProcessIdType = decltype(getpid()); 36 } // namespace mozilla::baseprofiler::detail 37 38 // --------------------------------------------- Non-Windows thread id 39 // ------------------------------------------------------- macOS 40 # if defined(XP_MACOSX) 41 42 namespace mozilla::baseprofiler::detail { 43 using ThreadIdType = uint64_t; 44 } // namespace mozilla::baseprofiler::detail 45 46 // ------------------------------------------------------- Android 47 // Test Android before Linux, because Linux includes Android. 48 # elif defined(__ANDROID__) || defined(ANDROID) 49 50 # include <sys/types.h> 51 namespace mozilla::baseprofiler::detail { 52 using ThreadIdType = decltype(gettid()); 53 } // namespace mozilla::baseprofiler::detail 54 55 // ------------------------------------------------------- Linux 56 # elif defined(XP_LINUX) 57 58 namespace mozilla::baseprofiler::detail { 59 using ThreadIdType = long; 60 } // namespace mozilla::baseprofiler::detail 61 62 // ------------------------------------------------------- FreeBSD 63 # elif defined(XP_FREEBSD) 64 65 namespace mozilla::baseprofiler::detail { 66 using ThreadIdType = long; 67 } // namespace mozilla::baseprofiler::detail 68 69 // ------------------------------------------------------- Others 70 # else 71 72 # include <thread> 73 74 namespace mozilla::baseprofiler::detail { 75 using ThreadIdType = std::thread::id; 76 } // namespace mozilla::baseprofiler::detail 77 78 # endif 79 #endif // End of non-XP_WIN. 80 81 #include <stdint.h> 82 #include <string.h> 83 #include <type_traits> 84 85 namespace mozilla::baseprofiler { 86 87 // Trivially-copyable class containing a process id. It may be left unspecified. 88 class BaseProfilerProcessId { 89 public: 90 using NativeType = detail::ProcessIdType; 91 92 using NumberType = 93 std::conditional_t<(sizeof(NativeType) <= 4), uint32_t, uint64_t>; 94 static_assert(sizeof(NativeType) <= sizeof(NumberType)); 95 96 // Unspecified process id. 97 constexpr BaseProfilerProcessId() = default; 98 99 [[nodiscard]] constexpr bool IsSpecified() const { 100 return mProcessId != scUnspecified; 101 } 102 103 // Construct from a native type. 104 [[nodiscard]] static BaseProfilerProcessId FromNativeId( 105 const NativeType& aNativeProcessId) { 106 BaseProfilerProcessId id; 107 // Convert trivially-copyable native id by copying its bits. 108 static_assert(std::is_trivially_copyable_v<NativeType>); 109 memcpy(&id.mProcessId, &aNativeProcessId, sizeof(NativeType)); 110 return id; 111 } 112 113 // Get the process id as a number, which may be unspecified. 114 // This should only be used for serialization or logging. 115 [[nodiscard]] constexpr NumberType ToNumber() const { return mProcessId; } 116 117 // BaseProfilerProcessId from given number (which may be unspecified). 118 constexpr static BaseProfilerProcessId FromNumber( 119 const NumberType& aProcessId) { 120 BaseProfilerProcessId id; 121 id.mProcessId = aProcessId; 122 return id; 123 } 124 125 [[nodiscard]] constexpr bool operator==( 126 const BaseProfilerProcessId& aOther) const { 127 return mProcessId == aOther.mProcessId; 128 } 129 [[nodiscard]] constexpr bool operator!=( 130 const BaseProfilerProcessId& aOther) const { 131 return mProcessId != aOther.mProcessId; 132 } 133 134 private: 135 static constexpr NumberType scUnspecified = 0; 136 NumberType mProcessId = scUnspecified; 137 }; 138 139 // Check traits. These should satisfy usage in std::atomic. 140 static_assert(std::is_trivially_copyable_v<BaseProfilerProcessId>); 141 static_assert(std::is_copy_constructible_v<BaseProfilerProcessId>); 142 static_assert(std::is_move_constructible_v<BaseProfilerProcessId>); 143 static_assert(std::is_copy_assignable_v<BaseProfilerProcessId>); 144 static_assert(std::is_move_assignable_v<BaseProfilerProcessId>); 145 146 // Trivially-copyable class containing a thread id. It may be left unspecified. 147 class BaseProfilerThreadId { 148 public: 149 using NativeType = detail::ThreadIdType; 150 151 using NumberType = 152 std::conditional_t<(sizeof(NativeType) <= 4), uint32_t, uint64_t>; 153 static_assert(sizeof(NativeType) <= sizeof(NumberType)); 154 155 // Unspecified thread id. 156 constexpr BaseProfilerThreadId() = default; 157 158 [[nodiscard]] constexpr bool IsSpecified() const { 159 return mThreadId != scUnspecified; 160 } 161 162 // Construct from a native type. 163 [[nodiscard]] static BaseProfilerThreadId FromNativeId( 164 const NativeType& aNativeThreadId) { 165 BaseProfilerThreadId id; 166 // Convert trivially-copyable native id by copying its bits. 167 static_assert(std::is_trivially_copyable_v<NativeType>); 168 memcpy(&id.mThreadId, &aNativeThreadId, sizeof(NativeType)); 169 return id; 170 } 171 172 // Get the thread id as a number, which may be unspecified. 173 // This should only be used for serialization or logging. 174 [[nodiscard]] constexpr NumberType ToNumber() const { return mThreadId; } 175 176 // BaseProfilerThreadId from given number (which may be unspecified). 177 constexpr static BaseProfilerThreadId FromNumber( 178 const NumberType& aThreadId) { 179 BaseProfilerThreadId id; 180 id.mThreadId = aThreadId; 181 return id; 182 } 183 184 [[nodiscard]] constexpr bool operator==( 185 const BaseProfilerThreadId& aOther) const { 186 return mThreadId == aOther.mThreadId; 187 } 188 [[nodiscard]] constexpr bool operator!=( 189 const BaseProfilerThreadId& aOther) const { 190 return mThreadId != aOther.mThreadId; 191 } 192 193 private: 194 static constexpr NumberType scUnspecified = 0; 195 NumberType mThreadId = scUnspecified; 196 }; 197 198 // Check traits. These should satisfy usage in std::atomic. 199 static_assert(std::is_trivially_copyable_v<BaseProfilerThreadId>); 200 static_assert(std::is_copy_constructible_v<BaseProfilerThreadId>); 201 static_assert(std::is_move_constructible_v<BaseProfilerThreadId>); 202 static_assert(std::is_copy_assignable_v<BaseProfilerThreadId>); 203 static_assert(std::is_move_assignable_v<BaseProfilerThreadId>); 204 205 } // namespace mozilla::baseprofiler 206 207 #include "mozilla/Types.h" 208 209 namespace mozilla::baseprofiler { 210 211 // Get the current process's ID. 212 [[nodiscard]] MFBT_API BaseProfilerProcessId profiler_current_process_id(); 213 214 // Get the current thread's ID. 215 [[nodiscard]] MFBT_API BaseProfilerThreadId profiler_current_thread_id(); 216 217 // Must be called at least once from the main thread, before any other main- 218 // thread id function. 219 MFBT_API void profiler_init_main_thread_id(); 220 221 [[nodiscard]] MFBT_API BaseProfilerThreadId profiler_main_thread_id(); 222 223 [[nodiscard]] MFBT_API bool profiler_is_main_thread(); 224 225 } // namespace mozilla::baseprofiler 226 227 #endif // BaseProfilerUtils_h