Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / base / platform / 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/time.h"
16
17 namespace v8 {
18 namespace base {
19
20 #if V8_OS_MACOSX
21
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);
26   USE(result);
27 }
28
29
30 Semaphore::~Semaphore() {
31   kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_);
32   DCHECK_EQ(KERN_SUCCESS, result);
33   USE(result);
34 }
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(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
90 void Semaphore::Signal() {
91   int result = sem_post(&native_handle_);
92   DCHECK_EQ(0, result);
93   USE(result);
94 }
95
96
97 void Semaphore::Wait() {
98   while (true) {
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);
104   }
105 }
106
107
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();
112
113   // Wait for semaphore signalled or timeout.
114   while (true) {
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)
118     if (result > 0) {
119       // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
120       errno = result;
121       result = -1;
122     }
123 #endif
124     if (result == -1 && errno == ETIMEDOUT) {
125       // Timed out while waiting for semaphore.
126       return false;
127     }
128     // Signal caused spurious wakeup.
129     DCHECK_EQ(-1, result);
130     DCHECK_EQ(EINTR, errno);
131   }
132 }
133
134 #elif V8_OS_WIN
135
136 Semaphore::Semaphore(int count) {
137   DCHECK(count >= 0);
138   native_handle_ = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL);
139   DCHECK(native_handle_ != NULL);
140 }
141
142
143 Semaphore::~Semaphore() {
144   BOOL result = CloseHandle(native_handle_);
145   DCHECK(result);
146   USE(result);
147 }
148
149
150 void Semaphore::Signal() {
151   LONG dummy;
152   BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
153   DCHECK(result);
154   USE(result);
155 }
156
157
158 void Semaphore::Wait() {
159   DWORD result = WaitForSingleObject(native_handle_, INFINITE);
160   DCHECK(result == WAIT_OBJECT_0);
161   USE(result);
162 }
163
164
165 bool Semaphore::WaitFor(const TimeDelta& rel_time) {
166   TimeTicks now = TimeTicks::Now();
167   TimeTicks end = now + rel_time;
168   while (true) {
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) {
173         return true;
174       }
175       DCHECK(result == WAIT_TIMEOUT);
176       now = TimeTicks::Now();
177     } else {
178       DWORD result = WaitForSingleObject(
179           native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
180       if (result == WAIT_TIMEOUT) {
181         return false;
182       }
183       DCHECK(result == WAIT_OBJECT_0);
184       return true;
185     }
186   }
187 }
188
189 #endif  // V8_OS_MACOSX
190
191 } }  // namespace v8::base