*/
static spinlock_t *threads_lock;
+/**
+ * Lock for setting condvars on threads
+ */
+static spinlock_t *condvar_lock;
+
/**
* Counter to assign printable thread IDs
*/
thread = get_current_thread();
- threads_lock->lock(threads_lock);
+ condvar_lock->lock(condvar_lock);
thread->condvar = condvar;
- threads_lock->unlock(threads_lock);
+ condvar_lock->unlock(condvar_lock);
/* this is a cancellation point, as condvar wait is one */
SleepEx(0, TRUE);
{
private_thread_t *this = (private_thread_t*)dwParam;
- /* make sure cancel() does not access this anymore */
- threads_lock->lock(threads_lock);
- threads_lock->unlock(threads_lock);
-
end_thread(this);
ExitThread(0);
}
METHOD(thread_t, cancel, void,
private_thread_t *this)
{
- this->canceled = TRUE;
- if (this->cancelability)
+ atomic_set_bool(&this->canceled, TRUE);
+ if (atomic_get_bool(&this->cancelability) &&
+ cas_bool(&this->cancel_pending, FALSE, TRUE))
{
- threads_lock->lock(threads_lock);
- if (!this->cancel_pending)
+ CONDITION_VARIABLE *cv;
+
+ condvar_lock->lock(condvar_lock);
+ cv = this->condvar;
+ QueueUserAPC(docancel, this->handle, (uintptr_t)this);
+ if (cv)
{
- this->cancel_pending = TRUE;
- QueueUserAPC(docancel, this->handle, (uintptr_t)this);
- if (this->condvar)
- {
- WakeAllConditionVariable(this->condvar);
- }
+ WakeAllConditionVariable(cv);
}
- threads_lock->unlock(threads_lock);
+ condvar_lock->unlock(condvar_lock);
}
}
static DWORD thread_cb(private_thread_t *this)
{
/* Enable cancelability once the thread starts. We must check for any
- * pending cancellation request an queue the APC that gets executed
+ * pending cancellation request and queue the APC that gets executed
* at the first cancellation point. */
- this->cancelability = TRUE;
- if (this->canceled)
+ atomic_set_bool(&this->cancelability, TRUE);
+ if (atomic_get_bool(&this->canceled))
{
cancel(this);
}
bool old;
this = get_current_thread();
- old = this->cancelability;
- this->cancelability = enable;
+ old = atomic_get_bool(&this->cancelability);
+ atomic_set_bool(&this->cancelability, enable);
- if (enable && !old && this->canceled)
+ if (enable && !old && atomic_get_bool(&this->canceled))
{
cancel(this);
}
void threads_init()
{
threads_lock = spinlock_create();
+ condvar_lock = spinlock_create();
threads = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4);
/* reset counter should we initialize more than once */
threads_lock->destroy(threads_lock);
threads_lock = NULL;
+ condvar_lock->destroy(condvar_lock);
+ condvar_lock = NULL;
threads->destroy(threads);
}