From 616b7afb724a32df41eebfaf95402d008c60b411 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 8 Sep 2010 19:13:49 -0700 Subject: [PATCH] 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. --- src/Makefile | 14 ++- src/rt/memory_region.h | 15 +++- src/rt/rust_internal.h | 2 +- src/rt/rust_kernel.cpp | 41 ++++----- src/rt/rust_kernel.h | 10 +-- src/rt/rust_log.cpp | 3 +- src/rt/sync/condition_variable.cpp | 84 ------------------ src/rt/sync/condition_variable.h | 20 ----- src/rt/sync/fair_ticket_lock.cpp | 43 --------- src/rt/sync/fair_ticket_lock.h | 15 ---- src/rt/sync/interrupt_transparent_queue.cpp | 56 ------------ src/rt/sync/interrupt_transparent_queue.h | 22 ----- src/rt/sync/lock_and_signal.cpp | 97 +++++++++++++++++++++ src/rt/sync/lock_and_signal.h | 23 +++++ src/rt/sync/spin_lock.cpp | 48 ---------- src/rt/sync/spin_lock.h | 14 --- src/rt/sync/sync.cpp | 9 +- src/rt/util/synchronized_indexed_list.h | 13 ++- 18 files changed, 182 insertions(+), 347 deletions(-) delete mode 100644 src/rt/sync/condition_variable.cpp delete mode 100644 src/rt/sync/condition_variable.h delete mode 100644 src/rt/sync/fair_ticket_lock.cpp delete mode 100644 src/rt/sync/fair_ticket_lock.h delete mode 100644 src/rt/sync/interrupt_transparent_queue.cpp delete mode 100644 src/rt/sync/interrupt_transparent_queue.h create mode 100755 src/rt/sync/lock_and_signal.cpp create mode 100644 src/rt/sync/lock_and_signal.h delete mode 100644 src/rt/sync/spin_lock.cpp delete mode 100644 src/rt/sync/spin_lock.h diff --git a/src/Makefile b/src/Makefile index dfe8a063b94..d44dba97d16 100644 --- a/src/Makefile +++ b/src/Makefile @@ -248,8 +248,7 @@ BOOT_CMIS := $(BOOT_MLS:.ml=.cmi) RUNTIME_CS := rt/sync/timer.cpp \ rt/sync/sync.cpp \ - rt/sync/spin_lock.cpp \ - rt/sync/condition_variable.cpp \ + rt/sync/lock_and_signal.cpp \ rt/rust.cpp \ rt/rust_builtin.cpp \ rt/rust_crate.cpp \ @@ -383,6 +382,9 @@ self: $(CFG_COMPILER) TASK_XFAILS := test/run-pass/task-comm-8.rs \ test/run-pass/task-comm-10.rs \ test/run-pass/task-comm-15.rs \ + test/run-pass/task-comm-12.rs \ + test/run-pass/task-comm-2.rs \ + test/run-pass/task-comm-9.rs \ test/run-pass/task-life-0.rs \ test/run-pass/alt-type-simple.rs \ test/run-pass/many.rs @@ -936,3 +938,11 @@ clean: $(CFG_QUIET)rm -Rf $(PKG_NAME)-*.tar.gz dist $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,\ $(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext))) + + +# Local Variables: +# mode: makefile-gmake +# fill-column: 78; +# buffer-file-coding-system: utf-8-unix +# compile-command: "make -k 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +# End: diff --git a/src/rt/memory_region.h b/src/rt/memory_region.h index affdd8f9974..b62f0f51611 100644 --- a/src/rt/memory_region.h +++ b/src/rt/memory_region.h @@ -9,7 +9,7 @@ #ifndef MEMORY_REGION_H #define MEMORY_REGION_H -#include "sync/spin_lock.h" +#include "sync/lock_and_signal.h" class rust_srv; @@ -20,7 +20,7 @@ private: size_t _live_allocations; array_list _allocation_list; const bool _synchronized; - spin_lock _lock; + lock_and_signal _lock; public: enum memory_region_type { LOCAL = 0x1, SYNCHRONIZED = 0x2 @@ -42,4 +42,15 @@ inline void *operator new(size_t size, memory_region *region) { return region->malloc(size); } +// +// 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: +// + #endif /* MEMORY_REGION_H */ diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index c327f8c055c..0913f9673a8 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -42,7 +42,7 @@ extern "C" { #include "util/hash_map.h" #include "sync/sync.h" #include "sync/timer.h" -#include "sync/condition_variable.h" +#include "sync/lock_and_signal.h" #include "sync/lock_free_queue.h" class rust_dom; diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index ae603379a17..b94c6c1aca0 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -12,7 +12,7 @@ rust_kernel::rust_kernel(rust_srv *srv) : rust_handle * rust_kernel::create_domain(const rust_crate *crate, const char *name) { - LOCK(_kernel_lock); + _kernel_lock.lock(); rust_message_queue *message_queue = new (this) rust_message_queue(_srv, this); rust_srv *srv = _srv->clone(); @@ -22,13 +22,14 @@ rust_kernel::create_domain(const rust_crate *crate, const char *name) { message_queue->associate(handle); domains.append(dom); message_queues.append(message_queue); - UNLOCK(_kernel_lock); + _kernel_lock.unlock(); + _kernel_lock.signal(); return handle; } void rust_kernel::destroy_domain(rust_dom *dom) { - LOCK(_kernel_lock); + _kernel_lock.lock(); log(rust_log::KERN, "deleting domain: " PTR ", index: %d, domains %d", dom, dom->list_index, domains.length()); domains.remove(dom); @@ -36,7 +37,8 @@ rust_kernel::destroy_domain(rust_dom *dom) { rust_srv *srv = dom->srv; delete dom; delete srv; - UNLOCK(_kernel_lock); + _kernel_lock.unlock(); + _kernel_lock.signal(); } rust_handle * @@ -52,15 +54,15 @@ rust_kernel::internal_get_dom_handle(rust_dom *dom) { rust_handle * rust_kernel::get_dom_handle(rust_dom *dom) { - LOCK(_kernel_lock); + _kernel_lock.lock(); rust_handle *handle = internal_get_dom_handle(dom); - UNLOCK(_kernel_lock); + _kernel_lock.unlock(); return handle; } rust_handle * rust_kernel::get_task_handle(rust_task *task) { - LOCK(_kernel_lock); + _kernel_lock.lock(); rust_handle *handle = NULL; if (_task_handles.get(task, &handle) == false) { handle = @@ -68,13 +70,13 @@ rust_kernel::get_task_handle(rust_task *task) { task); _task_handles.put(task, handle); } - UNLOCK(_kernel_lock); + _kernel_lock.unlock(); return handle; } rust_handle * rust_kernel::get_port_handle(rust_port *port) { - PLOCK(_kernel_lock); + _kernel_lock.lock(); rust_handle *handle = NULL; if (_port_handles.get(port, &handle) == false) { handle = @@ -83,7 +85,7 @@ rust_kernel::get_port_handle(rust_port *port) { port); _port_handles.put(port, handle); } - PUNLOCK(_kernel_lock); + _kernel_lock.unlock(); return handle; } @@ -126,7 +128,6 @@ rust_kernel::log(uint32_t type_bits, char const *fmt, ...) { void rust_kernel::pump_message_queues() { - LOCK(_kernel_lock); for (size_t i = 0; i < message_queues.length(); i++) { rust_message_queue *queue = message_queues[i]; if (queue->is_associated() == false) { @@ -137,27 +138,16 @@ rust_kernel::pump_message_queues() { } } } - UNLOCK(_kernel_lock); } void rust_kernel::start_kernel_loop() { + _kernel_lock.lock(); while (_interrupt_kernel_loop == false) { + _kernel_lock.wait(); pump_message_queues(); - - // FIXME: this is a complete hack to make the testsuite finish in a - // sane time when executing under valgrind. The whole message-loop - // system here needs replacement with an OS-level event-queue such - // that actually wait on inter-thread notices, rather than - // busy-waiting. - - size_t ms = TIME_SLICE_IN_MS; -#if defined(__WIN32__) - Sleep(ms); -#else - usleep(ms * 1000); -#endif } + _kernel_lock.unlock(); } void @@ -171,6 +161,7 @@ void rust_kernel::terminate_kernel_loop() { log(rust_log::KERN, "terminating kernel loop"); _interrupt_kernel_loop = true; + _kernel_lock.signal(); join(); } diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h index db3ad0687eb..6607bdbc3a3 100644 --- a/src/rt/rust_kernel.h +++ b/src/rt/rust_kernel.h @@ -32,12 +32,6 @@ public: } }; -#define LOCK(x) x.lock(); -#define UNLOCK(x) x.unlock(); - -#define PLOCK(x) printf("LOCKING @ %d\n", __LINE__); x.lock(); -#define PUNLOCK(x) x.unlock(); printf("UNLOCKED @ %d\n", __LINE__); - /** * A global object shared by all thread domains. Most of the data structures * in this class are synchronized since they are accessed from multiple @@ -59,9 +53,9 @@ class rust_kernel : public rust_thread { void run(); void start_kernel_loop(); - bool volatile _interrupt_kernel_loop; + bool _interrupt_kernel_loop; - spin_lock _kernel_lock; + lock_and_signal _kernel_lock; void terminate_kernel_loop(); void pump_message_queues(); diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp index fab5098d85a..a57f7cb49c9 100644 --- a/src/rt/rust_log.cpp +++ b/src/rt/rust_log.cpp @@ -4,7 +4,6 @@ */ #include "rust_internal.h" -#include "sync/spin_lock.h" #include "util/array_list.h" #include @@ -64,7 +63,7 @@ static const char * _foreground_colors[] = { "[37m", /** * Synchronizes access to the underlying logging mechanism. */ -static spin_lock _log_lock; +static lock_and_signal _log_lock; static uint32_t _last_thread_id; rust_log::rust_log(rust_srv *srv, rust_dom *dom) : 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; diff --git a/src/rt/util/synchronized_indexed_list.h b/src/rt/util/synchronized_indexed_list.h index a373db66deb..6b5611710d7 100644 --- a/src/rt/util/synchronized_indexed_list.h +++ b/src/rt/util/synchronized_indexed_list.h @@ -5,7 +5,7 @@ template class synchronized_indexed_list : public indexed_list { - spin_lock _lock; + lock_and_signal _lock; public: synchronized_indexed_list(memory_region *region) : @@ -61,4 +61,15 @@ public: } }; +// +// 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: +// + #endif /* SYNCHRONIZED_INDEXED_LIST_H */