diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2010-09-08 19:13:49 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2010-09-08 19:13:49 -0700 |
| commit | 616b7afb724a32df41eebfaf95402d008c60b411 (patch) | |
| tree | 03e13578e8b43b9001cef983d1117800a6f93e65 /src/rt/sync | |
| parent | 13d6f874316c9f69ab3a29f120ce410da2290a64 (diff) | |
| download | rust-616b7afb724a32df41eebfaf95402d008c60b411.tar.gz rust-616b7afb724a32df41eebfaf95402d008c60b411.zip | |
Tidy up the sync dir, remove dead or mis-designed code in favour of OS primitives, switch rust_kernel to use a lock/signal pair and wait rather than spin.
Diffstat (limited to 'src/rt/sync')
| -rw-r--r-- | src/rt/sync/condition_variable.cpp | 84 | ||||
| -rw-r--r-- | src/rt/sync/condition_variable.h | 20 | ||||
| -rw-r--r-- | src/rt/sync/fair_ticket_lock.cpp | 43 | ||||
| -rw-r--r-- | src/rt/sync/fair_ticket_lock.h | 15 | ||||
| -rw-r--r-- | src/rt/sync/interrupt_transparent_queue.cpp | 56 | ||||
| -rw-r--r-- | src/rt/sync/interrupt_transparent_queue.h | 22 | ||||
| -rwxr-xr-x | src/rt/sync/lock_and_signal.cpp | 97 | ||||
| -rw-r--r-- | src/rt/sync/lock_and_signal.h | 23 | ||||
| -rw-r--r-- | src/rt/sync/spin_lock.cpp | 48 | ||||
| -rw-r--r-- | src/rt/sync/spin_lock.h | 14 | ||||
| -rw-r--r-- | src/rt/sync/sync.cpp | 9 |
11 files changed, 125 insertions, 306 deletions
diff --git a/src/rt/sync/condition_variable.cpp b/src/rt/sync/condition_variable.cpp deleted file mode 100644 index c34ab7f42aa..00000000000 --- a/src/rt/sync/condition_variable.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "../globals.h" - -/* - * Conditional variable. Implemented using pthreads condition variables, and - * using events on windows. - */ - -#include "condition_variable.h" - -// #define TRACE - -#if defined(__WIN32__) -condition_variable::condition_variable() { - _event = CreateEvent(NULL, FALSE, FALSE, NULL); -} -#else -condition_variable::condition_variable() { - pthread_cond_init(&_cond, NULL); - pthread_mutex_init(&_mutex, NULL); -} -#endif - -condition_variable::~condition_variable() { -#if defined(__WIN32__) - CloseHandle(_event); -#else - pthread_cond_destroy(&_cond); - pthread_mutex_destroy(&_mutex); -#endif -} - -/** - * Wait indefinitely until condition is signaled. - */ -void condition_variable::wait() { - timed_wait(0); -} - -void condition_variable::timed_wait(size_t timeout_in_ns) { -#ifdef TRACE - printf("waiting on condition_variable: 0x%" PRIxPTR " for %d ns. \n", - (uintptr_t) this, (int) timeout_in_ns); -#endif -#if defined(__WIN32__) - WaitForSingleObject(_event, INFINITE); -#else - pthread_mutex_lock(&_mutex); - // wait() automatically releases the mutex while it waits, and acquires - // it right before exiting. This allows signal() to acquire the mutex - // when signaling.) - if (timeout_in_ns == 0) { - pthread_cond_wait(&_cond, &_mutex); - } else { - timeval time_val; - gettimeofday(&time_val, NULL); - timespec time_spec; - time_spec.tv_sec = time_val.tv_sec + 0; - time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ns; - pthread_cond_timedwait(&_cond, &_mutex, &time_spec); - } - pthread_mutex_unlock(&_mutex); -#endif -#ifdef TRACE - printf("resumed on condition_variable: 0x%" PRIxPTR "\n", - (uintptr_t)this); -#endif -} - -/** - * Signal condition, and resume the waiting thread. - */ -void condition_variable::signal() { -#if defined(__WIN32__) - SetEvent(_event); -#else - pthread_mutex_lock(&_mutex); - pthread_cond_signal(&_cond); - pthread_mutex_unlock(&_mutex); -#endif -#ifdef TRACE - printf("signal condition_variable: 0x%" PRIxPTR "\n", - (uintptr_t)this); -#endif -} diff --git a/src/rt/sync/condition_variable.h b/src/rt/sync/condition_variable.h deleted file mode 100644 index f336a7f2a6e..00000000000 --- a/src/rt/sync/condition_variable.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CONDITION_VARIABLE_H -#define CONDITION_VARIABLE_H - -class condition_variable { -#if defined(__WIN32__) - HANDLE _event; -#else - pthread_cond_t _cond; - pthread_mutex_t _mutex; -#endif -public: - condition_variable(); - virtual ~condition_variable(); - - void wait(); - void timed_wait(size_t timeout_in_ns); - void signal(); -}; - -#endif /* CONDITION_VARIABLE_H */ diff --git a/src/rt/sync/fair_ticket_lock.cpp b/src/rt/sync/fair_ticket_lock.cpp deleted file mode 100644 index 0306ee1df39..00000000000 --- a/src/rt/sync/fair_ticket_lock.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This works well as long as the number of contending threads - * is less than the number of processors. This is because of - * the fair locking scheme. If the thread that is next in line - * for acquiring the lock is not currently running, no other - * thread can acquire the lock. This is terrible for performance, - * and it seems that all fair locking schemes suffer from this - * behavior. - */ - -// #define TRACE - -fair_ticket_lock::fair_ticket_lock() { - next_ticket = now_serving = 0; -} - -fair_ticket_lock::~fair_ticket_lock() { - -} - -void fair_ticket_lock::lock() { - unsigned ticket = __sync_fetch_and_add(&next_ticket, 1); - while (now_serving != ticket) { - pause(); - } -#ifdef TRACE - printf("locked nextTicket: %d nowServing: %d", - next_ticket, now_serving); -#endif -} - -void fair_ticket_lock::unlock() { - now_serving++; -#ifdef TRACE - printf("unlocked nextTicket: %d nowServing: %d", - next_ticket, now_serving); -#endif -} - -void fair_ticket_lock::pause() { - asm volatile("pause\n" : : : "memory"); -} - diff --git a/src/rt/sync/fair_ticket_lock.h b/src/rt/sync/fair_ticket_lock.h deleted file mode 100644 index c34c9041657..00000000000 --- a/src/rt/sync/fair_ticket_lock.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FAIR_TICKET_LOCK_H -#define FAIR_TICKET_LOCK_H - -class fair_ticket_lock { - unsigned next_ticket; - unsigned now_serving; - void pause(); -public: - fair_ticket_lock(); - virtual ~fair_ticket_lock(); - void lock(); - void unlock(); -}; - -#endif /* FAIR_TICKET_LOCK_H */ diff --git a/src/rt/sync/interrupt_transparent_queue.cpp b/src/rt/sync/interrupt_transparent_queue.cpp deleted file mode 100644 index 064b25f17ba..00000000000 --- a/src/rt/sync/interrupt_transparent_queue.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Interrupt transparent queue, Schoen et. al, "On Interrupt-Transparent - * Synchronization in an Embedded Object-Oriented Operating System", 2000. - * enqueue() is allowed to interrupt enqueue() and dequeue(), however, - * dequeue() is not allowed to interrupt itself. - */ - -#include "../globals.h" -#include "interrupt_transparent_queue.h" - -interrupt_transparent_queue_node::interrupt_transparent_queue_node() : - next(NULL) { - -} - -interrupt_transparent_queue::interrupt_transparent_queue() : _tail(this) { - -} - -void -interrupt_transparent_queue::enqueue(interrupt_transparent_queue_node *item) { - lock.lock(); - item->next = (interrupt_transparent_queue_node *) NULL; - interrupt_transparent_queue_node *last = _tail; - _tail = item; - while (last->next) { - last = last->next; - } - last->next = item; - lock.unlock(); -} - -interrupt_transparent_queue_node * -interrupt_transparent_queue::dequeue() { - lock.lock(); - interrupt_transparent_queue_node *item = next; - if (item && !(next = item->next)) { - _tail = (interrupt_transparent_queue_node *) this; - if (item->next) { - interrupt_transparent_queue_node *lost = item->next; - interrupt_transparent_queue_node *help; - do { - help = lost->next; - enqueue(lost); - } while ((lost = help) != - (interrupt_transparent_queue_node *) NULL); - } - } - lock.unlock(); - return item; -} - -bool -interrupt_transparent_queue::is_empty() { - return next == NULL; -} diff --git a/src/rt/sync/interrupt_transparent_queue.h b/src/rt/sync/interrupt_transparent_queue.h deleted file mode 100644 index 7c02d0c8388..00000000000 --- a/src/rt/sync/interrupt_transparent_queue.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef INTERRUPT_TRANSPARENT_QUEUE_H -#define INTERRUPT_TRANSPARENT_QUEUE_H - -#include "spin_lock.h" - -class interrupt_transparent_queue_node { -public: - interrupt_transparent_queue_node *next; - interrupt_transparent_queue_node(); -}; - -class interrupt_transparent_queue : interrupt_transparent_queue_node { - spin_lock lock; - interrupt_transparent_queue_node *_tail; -public: - interrupt_transparent_queue(); - void enqueue(interrupt_transparent_queue_node *item); - interrupt_transparent_queue_node *dequeue(); - bool is_empty(); -}; - -#endif /* INTERRUPT_TRANSPARENT_QUEUE_H */ diff --git a/src/rt/sync/lock_and_signal.cpp b/src/rt/sync/lock_and_signal.cpp new file mode 100755 index 00000000000..c010086eb41 --- /dev/null +++ b/src/rt/sync/lock_and_signal.cpp @@ -0,0 +1,97 @@ +#include "../globals.h" + +/* + * A "lock-and-signal" pair. These are necessarily coupled on pthreads + * systems, and artificially coupled (by this file) on win32. Put + * together here to minimize ifdefs elsewhere; you must use them as + * if you're using a pthreads cvar+mutex pair. + */ + +#include "lock_and_signal.h" + +#if defined(__WIN32__) +lock_and_signal::lock_and_signal() { + _event = CreateEvent(NULL, FALSE, FALSE, NULL); + InitializeCriticalSection(&_cs); +} + +#else +lock_and_signal::lock_and_signal() { + pthread_cond_init(&_cond, NULL); + pthread_mutex_init(&_mutex, NULL); +} +#endif + +lock_and_signal::~lock_and_signal() { +#if defined(__WIN32__) + CloseHandle(_event); +#else + pthread_cond_destroy(&_cond); + pthread_mutex_destroy(&_mutex); +#endif +} + +void lock_and_signal::lock() { +#if defined(__WIN32__) + EnterCriticalSection(&_cs); +#else + pthread_mutex_lock(&_mutex); +#endif +} + +void lock_and_signal::unlock() { +#if defined(__WIN32__) + LeaveCriticalSection(&_cs); +#else + pthread_mutex_unlock(&_mutex); +#endif +} + + +/** + * Wait indefinitely until condition is signaled. + */ +void lock_and_signal::wait() { + timed_wait(0); +} + +void lock_and_signal::timed_wait(size_t timeout_in_ns) { +#if defined(__WIN32__) + LeaveCriticalSection(&_cs); + WaitForSingleObject(_event, INFINITE); + EnterCriticalSection(&_cs); +#else + if (timeout_in_ns == 0) { + pthread_cond_wait(&_cond, &_mutex); + } else { + timeval time_val; + gettimeofday(&time_val, NULL); + timespec time_spec; + time_spec.tv_sec = time_val.tv_sec + 0; + time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ns; + pthread_cond_timedwait(&_cond, &_mutex, &time_spec); + } +#endif +} + +/** + * Signal condition, and resume the waiting thread. + */ +void lock_and_signal::signal() { +#if defined(__WIN32__) + SetEvent(_event); +#else + pthread_cond_signal(&_cond); +#endif +} + + +// +// Local Variables: +// mode: C++ +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/rt/sync/lock_and_signal.h b/src/rt/sync/lock_and_signal.h new file mode 100644 index 00000000000..5a852d9d026 --- /dev/null +++ b/src/rt/sync/lock_and_signal.h @@ -0,0 +1,23 @@ +#ifndef LOCK_AND_SIGNAL_H +#define LOCK_AND_SIGNAL_H + +class lock_and_signal { +#if defined(__WIN32__) + HANDLE _event; + CRITICAL_SECTION _cs; +#else + pthread_cond_t _cond; + pthread_mutex_t _mutex; +#endif +public: + lock_and_signal(); + virtual ~lock_and_signal(); + + void lock(); + void unlock(); + void wait(); + void timed_wait(size_t timeout_in_ns); + void signal(); +}; + +#endif /* LOCK_AND_SIGNAL_H */ diff --git a/src/rt/sync/spin_lock.cpp b/src/rt/sync/spin_lock.cpp deleted file mode 100644 index 4a113d1aef9..00000000000 --- a/src/rt/sync/spin_lock.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "../globals.h" -#include "spin_lock.h" - -/* - * Your average spin lock. - */ - -// #define TRACE - -spin_lock::spin_lock() { - unlock(); -} - -spin_lock::~spin_lock() { -} - -static inline unsigned xchg32(void *ptr, unsigned x) { - __asm__ __volatile__("xchgl %0,%1" - :"=r" ((unsigned) x) - :"m" (*(volatile unsigned *)ptr), "0" (x) - :"memory"); - return x; -} - -void spin_lock::lock() { - while (true) { - if (!xchg32(&ticket, 1)) { - return; - } - while (ticket) { - pause(); - } - } -#ifdef TRACE - printf(" lock: %d", ticket); -#endif -} - -void spin_lock::unlock() { - ticket = 0; -#ifdef TRACE - printf("unlock:"); -#endif -} - -void spin_lock::pause() { - asm volatile("pause\n" : : : "memory"); -} diff --git a/src/rt/sync/spin_lock.h b/src/rt/sync/spin_lock.h deleted file mode 100644 index f15416a2d4e..00000000000 --- a/src/rt/sync/spin_lock.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPIN_LOCK_H -#define SPIN_LOCK_H - -class spin_lock { - unsigned ticket; - void pause(); -public: - spin_lock(); - virtual ~spin_lock(); - void lock(); - void unlock(); -}; - -#endif /* SPIN_LOCK_H */ diff --git a/src/rt/sync/sync.cpp b/src/rt/sync/sync.cpp index fdfc065249d..c754392aece 100644 --- a/src/rt/sync/sync.cpp +++ b/src/rt/sync/sync.cpp @@ -11,7 +11,7 @@ void sync::yield() { #endif } -rust_thread::rust_thread() : _is_running(false) { +rust_thread::rust_thread() : _is_running(false), thread(0) { // Nop. } @@ -25,7 +25,6 @@ static void * rust_thread_start(void *ptr) { rust_thread *thread = (rust_thread *) ptr; thread->run(); - thread->thread = 0; return 0; } @@ -46,9 +45,11 @@ rust_thread::start() { void rust_thread::join() { #if defined(__WIN32__) - WaitForSingleObject(thread, INFINITE); + if (thread) + WaitForSingleObject(thread, INFINITE); #else - pthread_join(thread, NULL); + if (thread) + pthread_join(thread, NULL); #endif thread = 0; _is_running = false; |
