1e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org// Copyright 2013 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 4e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 55de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/semaphore.h" 6e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 7e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_OS_MACOSX 8e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#include <mach/mach_init.h> 9e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#include <mach/task.h> 10e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif 11e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 12e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org#include <errno.h> 13e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 145de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/logging.h" 15d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org#include "src/base/platform/elapsed-timer.h" 165de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/time.h" 17e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 18e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgnamespace v8 { 195de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgnamespace base { 20e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 21e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_OS_MACOSX 22e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 23e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgSemaphore::Semaphore(int count) { 24e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org kern_return_t result = semaphore_create( 25e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org mach_task_self(), &native_handle_, SYNC_POLICY_FIFO, count); 26e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(KERN_SUCCESS, result); 27e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 28e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 29e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 30e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 31e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgSemaphore::~Semaphore() { 32e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_); 33e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(KERN_SUCCESS, result); 34e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 35e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 36e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 37e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 38e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid Semaphore::Signal() { 39e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org kern_return_t result = semaphore_signal(native_handle_); 40e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(KERN_SUCCESS, result); 41e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 42e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 43e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 44e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 45e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid Semaphore::Wait() { 46e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org while (true) { 47e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org kern_return_t result = semaphore_wait(native_handle_); 48e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == KERN_SUCCESS) return; // Semaphore was signalled. 49e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(KERN_ABORTED, result); 50e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 51e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 52e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 53e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 54e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgbool Semaphore::WaitFor(const TimeDelta& rel_time) { 55e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org TimeTicks now = TimeTicks::Now(); 56e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org TimeTicks end = now + rel_time; 57e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org while (true) { 58e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org mach_timespec_t ts; 59e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (now >= end) { 60e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // Return immediately if semaphore was not signalled. 61e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org ts.tv_sec = 0; 62e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org ts.tv_nsec = 0; 63e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } else { 64e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org ts = (end - now).ToMachTimespec(); 65e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 66e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org kern_return_t result = semaphore_timedwait(native_handle_, ts); 67e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == KERN_SUCCESS) return true; // Semaphore was signalled. 68e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == KERN_OPERATION_TIMED_OUT) return false; // Timeout. 69e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(KERN_ABORTED, result); 70e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org now = TimeTicks::Now(); 71e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 72e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 73e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 74e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#elif V8_OS_POSIX 75e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 76e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgSemaphore::Semaphore(int count) { 77e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(count >= 0); 78e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org int result = sem_init(&native_handle_, 0, count); 79e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(0, result); 80e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 81e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 82e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 83e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 84e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgSemaphore::~Semaphore() { 85e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org int result = sem_destroy(&native_handle_); 86e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(0, result); 87e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 88e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 89e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 90e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 91e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid Semaphore::Signal() { 92e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org int result = sem_post(&native_handle_); 93e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(0, result); 94e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 95e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 96e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 97e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 98e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid Semaphore::Wait() { 99e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org while (true) { 100e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org int result = sem_wait(&native_handle_); 101e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == 0) return; // Semaphore was signalled. 102e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // Signal caused spurious wakeup. 103e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(-1, result); 104e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(EINTR, errno); 105e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 106e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 107e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 108e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 109e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgbool Semaphore::WaitFor(const TimeDelta& rel_time) { 110d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org#if V8_OS_NACL 111d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org // PNaCL doesn't support sem_timedwait, do ugly busy waiting. 112d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org ElapsedTimer timer; 113d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org timer.Start(); 114d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org do { 115d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org int result = sem_trywait(&native_handle_); 116d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org if (result == 0) return true; 11721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org DCHECK(errno == EAGAIN || errno == EINTR); 118d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org } while (!timer.HasExpired(rel_time)); 119d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org return false; 120d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org#else 121e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // Compute the time for end of timeout. 122e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org const Time time = Time::NowFromSystemTime() + rel_time; 123e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org const struct timespec ts = time.ToTimespec(); 124e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 125e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // Wait for semaphore signalled or timeout. 126e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org while (true) { 127e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org int result = sem_timedwait(&native_handle_, &ts); 128e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == 0) return true; // Semaphore was signalled. 129e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4) 130e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result > 0) { 131e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1. 132e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org errno = result; 133e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org result = -1; 134e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 135e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif 136e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == -1 && errno == ETIMEDOUT) { 137e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // Timed out while waiting for semaphore. 138e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org return false; 139e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 140e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org // Signal caused spurious wakeup. 141e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(-1, result); 142e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(EINTR, errno); 143e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 144d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org#endif 145e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 146e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 147e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#elif V8_OS_WIN 148e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 149e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgSemaphore::Semaphore(int count) { 150e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(count >= 0); 151e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org native_handle_ = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL); 152e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(native_handle_ != NULL); 153e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 154e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 155e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 156e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgSemaphore::~Semaphore() { 157e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org BOOL result = CloseHandle(native_handle_); 158e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(result); 159e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 160e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 161e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 162e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 163e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid Semaphore::Signal() { 164e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org LONG dummy; 165e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy); 166e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(result); 167e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 168e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 169e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 170e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 171e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid Semaphore::Wait() { 172e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org DWORD result = WaitForSingleObject(native_handle_, INFINITE); 173e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(result == WAIT_OBJECT_0); 174e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org USE(result); 175e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 176e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 177e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 178e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgbool Semaphore::WaitFor(const TimeDelta& rel_time) { 179e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org TimeTicks now = TimeTicks::Now(); 180e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org TimeTicks end = now + rel_time; 181e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org while (true) { 182e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org int64_t msec = (end - now).InMilliseconds(); 183e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (msec >= static_cast<int64_t>(INFINITE)) { 184e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1); 185e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == WAIT_OBJECT_0) { 186e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org return true; 187e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 188e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(result == WAIT_TIMEOUT); 189e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org now = TimeTicks::Now(); 190e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } else { 191e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org DWORD result = WaitForSingleObject( 192e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec)); 193e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (result == WAIT_TIMEOUT) { 194e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org return false; 195e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 196e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(result == WAIT_OBJECT_0); 197e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org return true; 198e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 199e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org } 200e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org} 201e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 202e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif // V8_OS_MACOSX 203e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org 2045de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org} } // namespace v8::base 205