V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
semaphore.cc
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 
5 #include "src/base/platform/semaphore.h"
6 
7 #if V8_OS_MACOSX
8 #include <mach/mach_init.h>
9 #include <mach/task.h>
10 #endif
11 
12 #include <errno.h>
13 
14 #include "src/base/logging.h"
15 #include "src/base/platform/elapsed-timer.h"
16 #include "src/base/platform/time.h"
17 
18 namespace v8 {
19 namespace base {
20 
21 #if V8_OS_MACOSX
22 
23 Semaphore::Semaphore(int count) {
24  kern_return_t result = semaphore_create(
25  mach_task_self(), &native_handle_, SYNC_POLICY_FIFO, count);
26  DCHECK_EQ(KERN_SUCCESS, result);
27  USE(result);
28 }
29 
30 
31 Semaphore::~Semaphore() {
32  kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_);
33  DCHECK_EQ(KERN_SUCCESS, result);
34  USE(result);
35 }
36 
37 void Semaphore::Signal() {
38  kern_return_t result = semaphore_signal(native_handle_);
39  DCHECK_EQ(KERN_SUCCESS, result);
40  USE(result);
41 }
42 
43 
44 void Semaphore::Wait() {
45  while (true) {
46  kern_return_t result = semaphore_wait(native_handle_);
47  if (result == KERN_SUCCESS) return; // Semaphore was signalled.
48  DCHECK_EQ(KERN_ABORTED, result);
49  }
50 }
51 
52 
53 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
54  TimeTicks now = TimeTicks::Now();
55  TimeTicks end = now + rel_time;
56  while (true) {
57  mach_timespec_t ts;
58  if (now >= end) {
59  // Return immediately if semaphore was not signalled.
60  ts.tv_sec = 0;
61  ts.tv_nsec = 0;
62  } else {
63  ts = (end - now).ToMachTimespec();
64  }
65  kern_return_t result = semaphore_timedwait(native_handle_, ts);
66  if (result == KERN_SUCCESS) return true; // Semaphore was signalled.
67  if (result == KERN_OPERATION_TIMED_OUT) return false; // Timeout.
68  DCHECK_EQ(KERN_ABORTED, result);
69  now = TimeTicks::Now();
70  }
71 }
72 
73 #elif V8_OS_POSIX
74 
75 Semaphore::Semaphore(int count) {
76  DCHECK_GE(count, 0);
77  int result = sem_init(&native_handle_, 0, count);
78  DCHECK_EQ(0, result);
79  USE(result);
80 }
81 
82 
83 Semaphore::~Semaphore() {
84  int result = sem_destroy(&native_handle_);
85  DCHECK_EQ(0, result);
86  USE(result);
87 }
88 
89 void Semaphore::Signal() {
90  int result = sem_post(&native_handle_);
91  // This check may fail with <libc-2.21, which we use on the try bots, if the
92  // semaphore is destroyed while sem_post is still executed. A work around is
93  // to extend the lifetime of the semaphore.
94  if (result != 0) {
95  FATAL("Error when signaling semaphore, errno: %d", errno);
96  }
97 }
98 
99 
100 void Semaphore::Wait() {
101  while (true) {
102  int result = sem_wait(&native_handle_);
103  if (result == 0) return; // Semaphore was signalled.
104  // Signal caused spurious wakeup.
105  DCHECK_EQ(-1, result);
106  DCHECK_EQ(EINTR, errno);
107  }
108 }
109 
110 
111 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
112  // Compute the time for end of timeout.
113  const Time time = Time::NowFromSystemTime() + rel_time;
114  const struct timespec ts = time.ToTimespec();
115 
116  // Wait for semaphore signalled or timeout.
117  while (true) {
118  int result = sem_timedwait(&native_handle_, &ts);
119  if (result == 0) return true; // Semaphore was signalled.
120 #if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
121  if (result > 0) {
122  // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
123  errno = result;
124  result = -1;
125  }
126 #endif
127  if (result == -1 && errno == ETIMEDOUT) {
128  // Timed out while waiting for semaphore.
129  return false;
130  }
131  // Signal caused spurious wakeup.
132  DCHECK_EQ(-1, result);
133  DCHECK_EQ(EINTR, errno);
134  }
135 }
136 
137 #elif V8_OS_WIN
138 
139 Semaphore::Semaphore(int count) {
140  DCHECK_GE(count, 0);
141  native_handle_ = ::CreateSemaphoreA(nullptr, count, 0x7FFFFFFF, nullptr);
142  DCHECK_NOT_NULL(native_handle_);
143 }
144 
145 
146 Semaphore::~Semaphore() {
147  BOOL result = CloseHandle(native_handle_);
148  DCHECK(result);
149  USE(result);
150 }
151 
152 void Semaphore::Signal() {
153  LONG dummy;
154  BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
155  DCHECK(result);
156  USE(result);
157 }
158 
159 
160 void Semaphore::Wait() {
161  DWORD result = WaitForSingleObject(native_handle_, INFINITE);
162  DCHECK(result == WAIT_OBJECT_0);
163  USE(result);
164 }
165 
166 
167 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
168  TimeTicks now = TimeTicks::Now();
169  TimeTicks end = now + rel_time;
170  while (true) {
171  int64_t msec = (end - now).InMilliseconds();
172  if (msec >= static_cast<int64_t>(INFINITE)) {
173  DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
174  if (result == WAIT_OBJECT_0) {
175  return true;
176  }
177  DCHECK(result == WAIT_TIMEOUT);
178  now = TimeTicks::Now();
179  } else {
180  DWORD result = WaitForSingleObject(
181  native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
182  if (result == WAIT_TIMEOUT) {
183  return false;
184  }
185  DCHECK(result == WAIT_OBJECT_0);
186  return true;
187  }
188  }
189 }
190 
191 #endif // V8_OS_MACOSX
192 
193 } // namespace base
194 } // namespace v8
Definition: libplatform.h:13