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.
5 #include "src/base/platform/semaphore.h"
8 #include <mach/mach_init.h>
14 #include "src/base/logging.h"
15 #include "src/base/platform/time.h"
22 Semaphore::Semaphore(int count) {
23 kern_return_t result = semaphore_create(
24 mach_task_self(), &native_handle_, SYNC_POLICY_FIFO, count);
25 DCHECK_EQ(KERN_SUCCESS, result);
30 Semaphore::~Semaphore() {
31 kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_);
32 DCHECK_EQ(KERN_SUCCESS, result);
37 void Semaphore::Signal() {
38 kern_return_t result = semaphore_signal(native_handle_);
39 DCHECK_EQ(KERN_SUCCESS, result);
44 void Semaphore::Wait() {
46 kern_return_t result = semaphore_wait(native_handle_);
47 if (result == KERN_SUCCESS) return; // Semaphore was signalled.
48 DCHECK_EQ(KERN_ABORTED, result);
53 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
54 TimeTicks now = TimeTicks::Now();
55 TimeTicks end = now + rel_time;
59 // Return immediately if semaphore was not signalled.
63 ts = (end - now).ToMachTimespec();
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();
75 Semaphore::Semaphore(int count) {
77 int result = sem_init(&native_handle_, 0, count);
83 Semaphore::~Semaphore() {
84 int result = sem_destroy(&native_handle_);
90 void Semaphore::Signal() {
91 int result = sem_post(&native_handle_);
97 void Semaphore::Wait() {
99 int result = sem_wait(&native_handle_);
100 if (result == 0) return; // Semaphore was signalled.
101 // Signal caused spurious wakeup.
102 DCHECK_EQ(-1, result);
103 DCHECK_EQ(EINTR, errno);
108 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
109 // Compute the time for end of timeout.
110 const Time time = Time::NowFromSystemTime() + rel_time;
111 const struct timespec ts = time.ToTimespec();
113 // Wait for semaphore signalled or timeout.
115 int result = sem_timedwait(&native_handle_, &ts);
116 if (result == 0) return true; // Semaphore was signalled.
117 #if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
119 // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
124 if (result == -1 && errno == ETIMEDOUT) {
125 // Timed out while waiting for semaphore.
128 // Signal caused spurious wakeup.
129 DCHECK_EQ(-1, result);
130 DCHECK_EQ(EINTR, errno);
136 Semaphore::Semaphore(int count) {
138 native_handle_ = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL);
139 DCHECK(native_handle_ != NULL);
143 Semaphore::~Semaphore() {
144 BOOL result = CloseHandle(native_handle_);
150 void Semaphore::Signal() {
152 BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
158 void Semaphore::Wait() {
159 DWORD result = WaitForSingleObject(native_handle_, INFINITE);
160 DCHECK(result == WAIT_OBJECT_0);
165 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
166 TimeTicks now = TimeTicks::Now();
167 TimeTicks end = now + rel_time;
169 int64_t msec = (end - now).InMilliseconds();
170 if (msec >= static_cast<int64_t>(INFINITE)) {
171 DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
172 if (result == WAIT_OBJECT_0) {
175 DCHECK(result == WAIT_TIMEOUT);
176 now = TimeTicks::Now();
178 DWORD result = WaitForSingleObject(
179 native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
180 if (result == WAIT_TIMEOUT) {
183 DCHECK(result == WAIT_OBJECT_0);
189 #endif // V8_OS_MACOSX
191 } } // namespace v8::base