| // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| #ifndef RUNTIME_PLATFORM_THREADS_H_ | |
| #define RUNTIME_PLATFORM_THREADS_H_ | |
| #include "platform/assert.h" | |
| #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \ | |
| defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID) | |
| #include <pthread.h> | |
| #endif | |
| namespace dart { | |
| namespace platform { | |
| #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \ | |
| defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID) | |
| typedef pthread_t ThreadId; | |
| #elif defined(DART_HOST_OS_WINDOWS) | |
| typedef DWORD ThreadId; | |
| #else | |
| #error Unknown target os. | |
| #endif | |
| static constexpr ThreadId kInvalidThreadId = static_cast<ThreadId>(0); | |
| inline ThreadId GetCurrentThreadId() { | |
| #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \ | |
| defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID) | |
| return pthread_self(); | |
| #elif defined(DART_HOST_OS_WINDOWS) | |
| return ::GetCurrentThreadId(); | |
| #else | |
| #error Unknown target os. | |
| #endif | |
| } | |
| inline bool AreSameThreads(ThreadId a, ThreadId b) { | |
| #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \ | |
| defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID) | |
| return pthread_equal(a, b) != 0; | |
| #elif defined(DART_HOST_OS_WINDOWS) | |
| return a == b; | |
| #else | |
| #error Unknown target os. | |
| #endif | |
| } | |
| #if defined(DEBUG) | |
| class ThreadBoundResource { | |
| public: | |
| ~ThreadBoundResource() { ASSERT(owner_ == kUnowned); } | |
| void Acquire() { | |
| ASSERT(owner_ == kUnowned); | |
| owner_ = GetCurrentThreadId(); | |
| } | |
| void Release() { | |
| ASSERT(IsOwnedByCurrentThread()); | |
| owner_ = kUnowned; | |
| } | |
| bool IsOwnedByCurrentThread() const { | |
| return AreSameThreads(owner_, GetCurrentThreadId()); | |
| } | |
| private: | |
| static constexpr ThreadId kUnowned = kInvalidThreadId; | |
| ThreadId owner_ = kUnowned; | |
| }; | |
| #else | |
| class ThreadBoundResource { | |
| public: | |
| void Acquire() {} | |
| void Release() {} | |
| bool IsOwnedByCurrentThread() const { | |
| UNREACHABLE(); | |
| return false; | |
| } | |
| }; | |
| #endif | |
| } // namespace platform | |
| #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \ | |
| defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID) | |
| #define VALIDATE_PTHREAD_RESULT(result) \ | |
| if (result != 0) { \ | |
| const int kBufferSize = 1024; \ | |
| char error_buf[kBufferSize]; \ | |
| FATAL("pthread error: %d (%s)", result, \ | |
| Utils::StrError(result, error_buf, kBufferSize)); \ | |
| } | |
| #if defined(DEBUG) | |
| #define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result) | |
| #else | |
| // NOTE: This (currently) expands to a no-op. | |
| #define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0) | |
| #endif | |
| #ifdef DEBUG | |
| #define RETURN_ON_PTHREAD_FAILURE(result) \ | |
| if (result != 0) { \ | |
| const int kBufferSize = 1024; \ | |
| char error_buf[kBufferSize]; \ | |
| fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \ | |
| result, Utils::StrError(result, error_buf, kBufferSize)); \ | |
| return result; \ | |
| } | |
| #else | |
| #define RETURN_ON_PTHREAD_FAILURE(result) \ | |
| if (result != 0) return result; | |
| #endif | |
| #endif | |
| } // namespace dart | |
| #endif // RUNTIME_PLATFORM_THREADS_H_ |