Module: wine Branch: master Commit: a11c8758b2e2c70d4a4cc5ad693b56ef7a5ad05d URL: http://source.winehq.org/git/wine.git/?a=commit;h=a11c8758b2e2c70d4a4cc5ad69...
Author: Yifu Wang ywang@esri.com Date: Tue Dec 30 15:03:36 2014 -0800
msvcr120: Fixed bugs in Concurrency::critical_section.
---
dlls/msvcrt/lock.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/dlls/msvcrt/lock.c b/dlls/msvcrt/lock.c index 328b5b5..6d903dc 100644 --- a/dlls/msvcrt/lock.c +++ b/dlls/msvcrt/lock.c @@ -384,10 +384,11 @@ void __thiscall critical_section_lock(critical_section *this) NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); }
- this->unk_active.next = NULL; - if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q) - spin_wait_for_next_cs(&q); cs_set_head(this, &q); + if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q) { + spin_wait_for_next_cs(&q); + this->unk_active.next = q.next; + } }
/* ?try_lock@critical_section@Concurrency@@QAE_NXZ */ @@ -406,11 +407,11 @@ MSVCRT_bool __thiscall critical_section_try_lock(critical_section *this)
memset(&q, 0, sizeof(q)); if(!InterlockedCompareExchangePointer(&this->tail, &q, NULL)) { - this->unk_active.next = NULL; - if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q) - spin_wait_for_next_cs(&q); - cs_set_head(this, &q); + if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q) { + spin_wait_for_next_cs(&q); + this->unk_active.next = q.next; + } return TRUE; } return FALSE; @@ -437,8 +438,10 @@ void __thiscall critical_section_unlock(critical_section *this) break;
next = this->unk_active.next; - if(InterlockedCompareExchangePointer(&this->tail, NULL, next) == next) + if(InterlockedCompareExchangePointer(&this->tail, NULL, next) == next) { + HeapFree(GetProcessHeap(), 0, next); return; + } spin_wait_for_next_cs(next);
this->unk_active.next = next->next; @@ -491,14 +494,18 @@ MSVCRT_bool __thiscall critical_section_try_lock_for( if(status == STATUS_TIMEOUT) { if(!InterlockedExchange(&q->free, TRUE)) return FALSE; + /* A thread has signaled the event and is block waiting. */ + /* We need to catch the event to wake the thread. */ + NtWaitForKeyedEvent(keyed_event, q, 0, NULL); } }
- this->unk_active.next = NULL; - if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, q) != q) + cs_set_head(this, q); + if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, q) != q) { spin_wait_for_next_cs(q); + this->unk_active.next = q->next; + }
- cs_set_head(this, q); HeapFree(GetProcessHeap(), 0, q); return TRUE; }