Author: [email protected]
Date: Wed Mar 18 02:04:24 2009
New Revision: 1526
Modified:
branches/bleeding_edge/SConstruct
branches/bleeding_edge/src/platform-freebsd.cc
branches/bleeding_edge/src/platform-linux.cc
branches/bleeding_edge/src/platform-macos.cc
branches/bleeding_edge/src/platform-win32.cc
branches/bleeding_edge/src/platform.h
branches/bleeding_edge/test/cctest/test-lock.cc
Log:
Added a wait with timeout to the platform semaphore class.
The code has been compiled and tested on Windows, Linux and Mac OS.
The FreeBSD version is a copy of the Linux version which should work on
FreeBSD as well. According to the FreeBSD documentation clock_gettime is
part of the standard C library so the assumption is that no additional link
libraries is required for FreeBSD.
Review URL: http://codereview.chromium.org/48123
Modified: branches/bleeding_edge/SConstruct
==============================================================================
--- branches/bleeding_edge/SConstruct (original)
+++ branches/bleeding_edge/SConstruct Wed Mar 18 02:04:24 2009
@@ -151,7 +151,7 @@
MKSNAPSHOT_EXTRA_FLAGS = {
'gcc': {
'os:linux': {
- 'LIBS': ['pthread'],
+ 'LIBS': ['pthread', 'rt'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -195,7 +195,7 @@
'LIBPATH': [abspath('.')]
},
'os:linux': {
- 'LIBS': ['pthread'],
+ 'LIBS': ['pthread', 'rt'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -233,7 +233,7 @@
'LIBPATH': ['.']
},
'os:linux': {
- 'LIBS': ['pthread'],
+ 'LIBS': ['pthread', 'rt'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -301,7 +301,7 @@
'LIBS': ['readline']
},
'os:linux': {
- 'LIBS': ['pthread'],
+ 'LIBS': ['pthread', 'rt'],
},
'os:macos': {
'LIBS': ['pthread'],
Modified: branches/bleeding_edge/src/platform-freebsd.cc
==============================================================================
--- branches/bleeding_edge/src/platform-freebsd.cc (original)
+++ branches/bleeding_edge/src/platform-freebsd.cc Wed Mar 18 02:04:24 2009
@@ -608,11 +608,13 @@
virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); }
virtual void Wait();
+ virtual bool Wait(int timeout);
virtual void Signal() { sem_post(&sem_); }
private:
sem_t sem_;
};
+
void FreeBSDSemaphore::Wait() {
while (true) {
int result = sem_wait(&sem_);
@@ -620,6 +622,39 @@
CHECK(result == -1 && errno == EINTR); // Signal caused spurious
wakeup.
}
}
+
+
+bool FreeBSDSemaphore::Wait(int timeout) {
+ const long kOneSecondMicros = 1000000; // NOLINT
+ const long kOneSecondNanos = 1000000000; // NOLINT
+
+ // Split timeout into second and nanosecond parts.
+ long nanos = (timeout % kOneSecondMicros) * 1000; // NOLINT
+ time_t secs = timeout / kOneSecondMicros;
+
+ // Get the current real time clock.
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ return false;
+ }
+
+ // Calculate realtime for end of timeout.
+ ts.tv_nsec += nanos;
+ if (ts.tv_nsec >= kOneSecondNanos) {
+ ts.tv_nsec -= kOneSecondNanos;
+ ts.tv_nsec++;
+ }
+ ts.tv_sec += secs;
+
+ // Wait for semaphore signalled or timeout.
+ while (true) {
+ int result = sem_timedwait(&sem_, &ts);
+ if (result == 0) return true; // Successfully got semaphore.
+ if (result == -1 && errno == ETIMEDOUT) return false; // Timeout.
+ CHECK(result == -1 && errno == EINTR); // Signal caused spurious
wakeup.
+ }
+}
+
Semaphore* OS::CreateSemaphore(int count) {
return new FreeBSDSemaphore(count);
Modified: branches/bleeding_edge/src/platform-linux.cc
==============================================================================
--- branches/bleeding_edge/src/platform-linux.cc (original)
+++ branches/bleeding_edge/src/platform-linux.cc Wed Mar 18 02:04:24 2009
@@ -592,11 +592,13 @@
virtual ~LinuxSemaphore() { sem_destroy(&sem_); }
virtual void Wait();
+ virtual bool Wait(int timeout);
virtual void Signal() { sem_post(&sem_); }
private:
sem_t sem_;
};
+
void LinuxSemaphore::Wait() {
while (true) {
int result = sem_wait(&sem_);
@@ -604,6 +606,39 @@
CHECK(result == -1 && errno == EINTR); // Signal caused spurious
wakeup.
}
}
+
+
+bool LinuxSemaphore::Wait(int timeout) {
+ const long kOneSecondMicros = 1000000; // NOLINT
+ const long kOneSecondNanos = 1000000000; // NOLINT
+
+ // Split timeout into second and nanosecond parts.
+ long nanos = (timeout % kOneSecondMicros) * 1000; // NOLINT
+ time_t secs = timeout / kOneSecondMicros;
+
+ // Get the current realtime clock.
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ return false;
+ }
+
+ // Calculate real time for end of timeout.
+ ts.tv_nsec += nanos;
+ if (ts.tv_nsec >= kOneSecondNanos) {
+ ts.tv_nsec -= kOneSecondNanos;
+ ts.tv_nsec++;
+ }
+ ts.tv_sec += secs;
+
+ // Wait for semaphore signalled or timeout.
+ while (true) {
+ int result = sem_timedwait(&sem_, &ts);
+ if (result == 0) return true; // Successfully got semaphore.
+ if (result == -1 && errno == ETIMEDOUT) return false; // Timeout.
+ CHECK(result == -1 && errno == EINTR); // Signal caused spurious
wakeup.
+ }
+}
+
Semaphore* OS::CreateSemaphore(int count) {
return new LinuxSemaphore(count);
Modified: branches/bleeding_edge/src/platform-macos.cc
==============================================================================
--- branches/bleeding_edge/src/platform-macos.cc (original)
+++ branches/bleeding_edge/src/platform-macos.cc Wed Mar 18 02:04:24 2009
@@ -565,11 +565,21 @@
// platform is not needed here.
void Wait() { semaphore_wait(semaphore_); }
+ bool Wait(int timeout);
+
void Signal() { semaphore_signal(semaphore_); }
private:
semaphore_t semaphore_;
};
+
+
+bool MacOSSemaphore::Wait(int timeout) {
+ mach_timespec_t ts;
+ ts.tv_sec = timeout / 1000000;
+ ts.tv_nsec = (timeout % 1000000) * 1000;
+ return semaphore_timedwait(semaphore_, ts) != KERN_OPERATION_TIMED_OUT;
+}
Semaphore* OS::CreateSemaphore(int count) {
Modified: branches/bleeding_edge/src/platform-win32.cc
==============================================================================
--- branches/bleeding_edge/src/platform-win32.cc (original)
+++ branches/bleeding_edge/src/platform-win32.cc Wed Mar 18 02:04:24 2009
@@ -1538,6 +1538,12 @@
WaitForSingleObject(sem, INFINITE);
}
+ bool Wait(int timeout) {
+ // Timeout in Windows API is in milliseconds.
+ DWORD millis_timeout = timeout / 1000;
+ return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT;
+ }
+
void Signal() {
LONG dummy;
ReleaseSemaphore(sem, 1, &dummy);
Modified: branches/bleeding_edge/src/platform.h
==============================================================================
--- branches/bleeding_edge/src/platform.h (original)
+++ branches/bleeding_edge/src/platform.h Wed Mar 18 02:04:24 2009
@@ -410,9 +410,15 @@
public:
virtual ~Semaphore() {}
- // Suspends the calling thread until the counter is non zero
+ // Suspends the calling thread until the semaphore counter is non zero
// and then decrements the semaphore counter.
virtual void Wait() = 0;
+
+ // Suspends the calling thread until the counter is non zero or the
timeout
+ // time has passsed. If timeout happens the return value is false and the
+ // counter is unchanged. Otherwise the semaphore counter is decremented
and
+ // true is returned. The timeout value is specified in microseconds.
+ virtual bool Wait(int timeout) = 0;
// Increments the semaphore counter.
virtual void Signal() = 0;
Modified: branches/bleeding_edge/test/cctest/test-lock.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-lock.cc (original)
+++ branches/bleeding_edge/test/cctest/test-lock.cc Wed Mar 18 02:04:24 2009
@@ -38,3 +38,26 @@
CHECK_EQ(0, mutex->Unlock());
delete mutex;
}
+
+
+TEST(SemaphoreTimeout) {
+ bool ok;
+ Semaphore* sem = OS::CreateSemaphore(0);
+
+ // Semaphore not signalled - timeout.
+ ok = sem->Wait(0);
+ CHECK(!ok);
+ ok = sem->Wait(100);
+ CHECK(!ok);
+ ok = sem->Wait(1000);
+ CHECK(!ok);
+
+ // Semaphore signalled - no timeout.
+ sem->Signal();
+ ok = sem->Wait(0);
+ sem->Signal();
+ ok = sem->Wait(100);
+ sem->Signal();
+ ok = sem->Wait(1000);
+ CHECK(ok);
+}
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---