v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
semaphore.cc
Go to the documentation of this file.
1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#if V8_OS_DARWIN
8#include <dispatch/dispatch.h>
9#elif V8_OS_WIN
10#include <windows.h>
11#endif
12
13#include <errno.h>
14
15#include "src/base/logging.h"
18
19namespace v8 {
20namespace base {
21
22#if V8_OS_DARWIN
23
24Semaphore::Semaphore(int count) {
25 native_handle_ = dispatch_semaphore_create(count);
27}
28
29Semaphore::~Semaphore() { dispatch_release(native_handle_); }
30
31void Semaphore::Signal() { dispatch_semaphore_signal(native_handle_); }
32
33void Semaphore::Wait() {
34 dispatch_semaphore_wait(native_handle_, DISPATCH_TIME_FOREVER);
35}
36
37
38bool Semaphore::WaitFor(const TimeDelta& rel_time) {
39 dispatch_time_t timeout =
40 dispatch_time(DISPATCH_TIME_NOW, rel_time.InNanoseconds());
41 return dispatch_semaphore_wait(native_handle_, timeout) == 0;
42}
43
44#elif V8_OS_POSIX
45
46Semaphore::Semaphore(int count) {
47 DCHECK_GE(count, 0);
48 int result = sem_init(&native_handle_, 0, count);
49 DCHECK_EQ(0, result);
50 USE(result);
51}
52
53
55 int result = sem_destroy(&native_handle_);
56 DCHECK_EQ(0, result);
57 USE(result);
58}
59
60void Semaphore::Signal() {
61 int result = sem_post(&native_handle_);
62 // This check may fail with <libc-2.21, which we use on the try bots, if the
63 // semaphore is destroyed while sem_post is still executed. A work around is
64 // to extend the lifetime of the semaphore.
65 if (result != 0) {
66 FATAL("Error when signaling semaphore, errno: %d", errno);
67 }
68}
69
70
71void Semaphore::Wait() {
72 while (true) {
73 int result = sem_wait(&native_handle_);
74 if (result == 0) return; // Semaphore was signalled.
75 // Signal caused spurious wakeup.
76 DCHECK_EQ(-1, result);
77 DCHECK_EQ(EINTR, errno);
78 }
79}
80
81
82bool Semaphore::WaitFor(const TimeDelta& rel_time) {
83 // Compute the time for end of timeout.
84 const Time time = Time::NowFromSystemTime() + rel_time;
85 const struct timespec ts = time.ToTimespec();
86
87 // Wait for semaphore signalled or timeout.
88 while (true) {
89 int result = sem_timedwait(&native_handle_, &ts);
90 if (result == 0) return true; // Semaphore was signalled.
91#if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
92 if (result > 0) {
93 // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
94 errno = result;
95 result = -1;
96 }
97#endif
98 if (result == -1 && errno == ETIMEDOUT) {
99 // Timed out while waiting for semaphore.
100 return false;
101 }
102 // Signal caused spurious wakeup.
103 DCHECK_EQ(-1, result);
104 DCHECK_EQ(EINTR, errno);
105 }
106}
107
108#elif V8_OS_WIN
109
110Semaphore::Semaphore(int count) {
111 DCHECK_GE(count, 0);
112 native_handle_ = ::CreateSemaphoreA(nullptr, count, 0x7FFFFFFF, nullptr);
114}
115
116
118 BOOL result = CloseHandle(native_handle_);
119 DCHECK(result);
120 USE(result);
121}
122
123void Semaphore::Signal() {
124 LONG dummy;
125 BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
126 DCHECK(result);
127 USE(result);
128}
129
130
131void Semaphore::Wait() {
132 DWORD result = WaitForSingleObject(native_handle_, INFINITE);
133 DCHECK(result == WAIT_OBJECT_0);
134 USE(result);
135}
136
137
138bool Semaphore::WaitFor(const TimeDelta& rel_time) {
139 TimeTicks now = TimeTicks::Now();
140 TimeTicks end = now + rel_time;
141 while (true) {
142 int64_t msec = (end - now).InMilliseconds();
143 if (msec >= static_cast<int64_t>(INFINITE)) {
144 DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
145 if (result == WAIT_OBJECT_0) {
146 return true;
147 }
148 DCHECK(result == WAIT_TIMEOUT);
149 now = TimeTicks::Now();
150 } else {
151 DWORD result = WaitForSingleObject(
152 native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
153 if (result == WAIT_TIMEOUT) {
154 return false;
155 }
156 DCHECK(result == WAIT_OBJECT_0);
157 return true;
158 }
159 }
160}
161
162#elif V8_OS_STARBOARD
163
164Semaphore::Semaphore(int count) : native_handle_(count) { DCHECK_GE(count, 0); }
165
166Semaphore::~Semaphore() {}
167
168void Semaphore::Signal() { native_handle_.Put(); }
169
170void Semaphore::Wait() { native_handle_.Take(); }
171
172bool Semaphore::WaitFor(const TimeDelta& rel_time) {
173 int64_t microseconds = rel_time.InMicroseconds();
174 return native_handle_.TakeWait(microseconds);
175}
176
177#endif // V8_OS_DARWIN
178
179} // namespace base
180} // namespace v8
Semaphore(int count)
NativeHandle native_handle_
Definition semaphore.h:78
bool WaitFor(const TimeDelta &rel_time) V8_WARN_UNUSED_RESULT
static TimeTicks Now()
Definition time.cc:736
static Time NowFromSystemTime()
struct timespec ToTimespec() const
int end
ZoneVector< RpoNumber > & result
#define FATAL(...)
Definition logging.h:47
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
int BOOL
long LONG
unsigned long DWORD