OLD | NEW |
| (Empty) |
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/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/checks.h" | |
15 #include "src/platform/time.h" | |
16 | |
17 namespace v8 { | |
18 namespace internal { | |
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 ASSERT_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 ASSERT_EQ(KERN_SUCCESS, result); | |
33 USE(result); | |
34 } | |
35 | |
36 | |
37 void Semaphore::Signal() { | |
38 kern_return_t result = semaphore_signal(native_handle_); | |
39 ASSERT_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 ASSERT_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 ASSERT_EQ(KERN_ABORTED, result); | |
69 now = TimeTicks::Now(); | |
70 } | |
71 } | |
72 | |
73 #elif V8_OS_POSIX | |
74 | |
75 Semaphore::Semaphore(int count) { | |
76 ASSERT(count >= 0); | |
77 int result = sem_init(&native_handle_, 0, count); | |
78 ASSERT_EQ(0, result); | |
79 USE(result); | |
80 } | |
81 | |
82 | |
83 Semaphore::~Semaphore() { | |
84 int result = sem_destroy(&native_handle_); | |
85 ASSERT_EQ(0, result); | |
86 USE(result); | |
87 } | |
88 | |
89 | |
90 void Semaphore::Signal() { | |
91 int result = sem_post(&native_handle_); | |
92 ASSERT_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 ASSERT_EQ(-1, result); | |
103 ASSERT_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 ASSERT_EQ(-1, result); | |
130 ASSERT_EQ(EINTR, errno); | |
131 } | |
132 } | |
133 | |
134 #elif V8_OS_WIN | |
135 | |
136 Semaphore::Semaphore(int count) { | |
137 ASSERT(count >= 0); | |
138 native_handle_ = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL); | |
139 ASSERT(native_handle_ != NULL); | |
140 } | |
141 | |
142 | |
143 Semaphore::~Semaphore() { | |
144 BOOL result = CloseHandle(native_handle_); | |
145 ASSERT(result); | |
146 USE(result); | |
147 } | |
148 | |
149 | |
150 void Semaphore::Signal() { | |
151 LONG dummy; | |
152 BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy); | |
153 ASSERT(result); | |
154 USE(result); | |
155 } | |
156 | |
157 | |
158 void Semaphore::Wait() { | |
159 DWORD result = WaitForSingleObject(native_handle_, INFINITE); | |
160 ASSERT(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 ASSERT(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 ASSERT(result == WAIT_OBJECT_0); | |
184 return true; | |
185 } | |
186 } | |
187 } | |
188 | |
189 #endif // V8_OS_MACOSX | |
190 | |
191 } } // namespace v8::internal | |
OLD | NEW |