Flutter Engine
The Flutter Engine
thread_absl.cc
Go to the documentation of this file.
1// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "platform/globals.h"
6#if defined(DART_USE_ABSL)
7
8#include <errno.h> // NOLINT
9#include <sys/resource.h> // NOLINT
10#include <sys/time.h> // NOLINT
11
12#include "bin/thread.h"
13#include "bin/thread_absl.h"
14#include "platform/assert.h"
15#include "platform/utils.h"
16
17namespace dart {
18namespace bin {
19
20#define VALIDATE_PTHREAD_RESULT(result) \
21 if (result != 0) { \
22 const int kBufferSize = 1024; \
23 char error_buf[kBufferSize]; \
24 FATAL("pthread error: %d (%s)", result, \
25 Utils::StrError(result, error_buf, kBufferSize)); \
26 }
27
28#ifdef DEBUG
29#define RETURN_ON_PTHREAD_FAILURE(result) \
30 if (result != 0) { \
31 const int kBufferSize = 1024; \
32 char error_buf[kBufferSize]; \
33 fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
34 result, Utils::StrError(result, error_buf, kBufferSize)); \
35 return result; \
36 }
37#else
38#define RETURN_ON_PTHREAD_FAILURE(result) \
39 if (result != 0) { \
40 return result; \
41 }
42#endif
43
44class ThreadStartData {
45 public:
46 ThreadStartData(const char* name,
48 uword parameter)
49 : name_(name), function_(function), parameter_(parameter) {}
50
51 const char* name() const { return name_; }
52 Thread::ThreadStartFunction function() const { return function_; }
53 uword parameter() const { return parameter_; }
54
55 private:
56 const char* name_;
58 uword parameter_;
59
60 DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
61};
62
63// Dispatch to the thread start function provided by the caller. This trampoline
64// is used to ensure that the thread is properly destroyed if the thread just
65// exits.
66static void* ThreadStart(void* data_ptr) {
67 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr);
68
69 const char* name = data->name();
71 uword parameter = data->parameter();
72 delete data;
73
74#if defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
75 // Set the thread name. There is 16 bytes limit on the name (including \0).
76 // pthread_setname_np ignores names that are too long rather than truncating.
77 char truncated_name[16];
78 snprintf(truncated_name, sizeof(truncated_name), "%s", name);
79 pthread_setname_np(pthread_self(), truncated_name);
80#elif defined(DART_HOST_OS_MACOS)
81 // Set the thread name.
82 pthread_setname_np(name);
83#endif
84
85 // Call the supplied thread start function handing it its parameters.
86 function(parameter);
87
88 return nullptr;
89}
90
91int Thread::Start(const char* name,
92 ThreadStartFunction function,
93 uword parameter) {
94 pthread_attr_t attr;
95 int result = pthread_attr_init(&attr);
96 RETURN_ON_PTHREAD_FAILURE(result);
97
98 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
99 RETURN_ON_PTHREAD_FAILURE(result);
100
101 result = pthread_attr_setstacksize(&attr, Thread::GetMaxStackSize());
102 RETURN_ON_PTHREAD_FAILURE(result);
103
104 ThreadStartData* data = new ThreadStartData(name, function, parameter);
105
106 pthread_t tid;
107 result = pthread_create(&tid, &attr, ThreadStart, data);
108 RETURN_ON_PTHREAD_FAILURE(result);
109
110 result = pthread_attr_destroy(&attr);
111 RETURN_ON_PTHREAD_FAILURE(result);
112
113 return 0;
114}
115
116const ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
117
118intptr_t Thread::GetMaxStackSize() {
119 const int kStackSize = (128 * kWordSize * KB);
120 return kStackSize;
121}
122
124 return pthread_self();
125}
126
128 return (pthread_equal(a, b) != 0);
129}
130
131Mutex::Mutex() : data_() {}
132
133Mutex::~Mutex() {}
134
135ABSL_NO_THREAD_SAFETY_ANALYSIS
136void Mutex::Lock() {
137 data_.mutex()->Lock();
138}
139
140ABSL_NO_THREAD_SAFETY_ANALYSIS
141bool Mutex::TryLock() {
142 if (!data_.mutex()->TryLock()) {
143 return false;
144 }
145 return true;
146}
147
148ABSL_NO_THREAD_SAFETY_ANALYSIS
149void Mutex::Unlock() {
150 data_.mutex()->Unlock();
151}
152
153Monitor::Monitor() : data_() {}
154
155Monitor::~Monitor() {}
156
157ABSL_NO_THREAD_SAFETY_ANALYSIS
158void Monitor::Enter() {
159 data_.mutex()->Lock();
160}
161
162ABSL_NO_THREAD_SAFETY_ANALYSIS
163void Monitor::Exit() {
164 data_.mutex()->Unlock();
165}
166
167Monitor::WaitResult Monitor::Wait(int64_t millis) {
168 return WaitMicros(millis * kMicrosecondsPerMillisecond);
169}
170
171ABSL_NO_THREAD_SAFETY_ANALYSIS
172Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
173 Monitor::WaitResult retval = kNotified;
174 if (micros == kNoTimeout) {
175 // Wait forever.
176 data_.cond()->Wait(data_.mutex());
177 } else {
178 if (data_.cond()->WaitWithTimeout(data_.mutex(),
179 absl::Microseconds(micros))) {
180 retval = kTimedOut;
181 }
182 }
183 return retval;
184}
185
186ABSL_NO_THREAD_SAFETY_ANALYSIS
187void Monitor::Notify() {
188 data_.cond()->Signal();
189}
190
191ABSL_NO_THREAD_SAFETY_ANALYSIS
192void Monitor::NotifyAll() {
193 data_.cond()->SignalAll();
194}
195
196} // namespace bin
197} // namespace dart
198
199#endif // defined(DART_USE_ABSL)
static const ThreadId kInvalidThreadId
Definition: thread.h:38
void(* ThreadStartFunction)(uword parameter)
Definition: thread.h:40
static intptr_t GetMaxStackSize()
static int Start(const char *name, ThreadStartFunction function, uword parameters)
static bool Compare(ThreadId a, ThreadId b)
static ThreadId GetCurrentThreadId()
static bool b
struct MyStruct a[10]
constexpr uint64_t kMicrosecondsPerMillisecond
GAsyncResult * result
Dart_NativeFunction function
Definition: fuchsia.cc:51
pthread_t ThreadId
Definition: thread_absl.h:21
Definition: dart_vm.cc:33
const char *const name
constexpr intptr_t KB
Definition: globals.h:528
uintptr_t uword
Definition: globals.h:501
constexpr intptr_t kWordSize
Definition: globals.h:509
static int8_t data[kExtLength]
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581