From 5175037b635d638e16396bee7890e4512031f866 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 24 Jun 2014 11:57:53 +0200 Subject: [PATCH] msvcr110: Add critical_section::try_lock_for implementation. --- dlls/msvcr110/msvcr110.spec | 6 ++-- dlls/msvcrt/lock.c | 72 +++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 57d7950a23a..4127725577d 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -794,9 +794,9 @@ @ stub -arch=arm ?try_lock@reader_writer_lock@Concurrency@@QAA_NXZ @ stub -arch=i386 ?try_lock@reader_writer_lock@Concurrency@@QAE_NXZ @ stub -arch=win64 ?try_lock@reader_writer_lock@Concurrency@@QEAA_NXZ -@ stub -arch=arm ?try_lock_for@critical_section@Concurrency@@QAA_NI@Z -@ stub -arch=i386 ?try_lock_for@critical_section@Concurrency@@QAE_NI@Z -@ stub -arch=win64 ?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z +@ cdecl -arch=arm ?try_lock_for@critical_section@Concurrency@@QAA_NI@Z(ptr long) critical_section_try_lock_for +@ thiscall -arch=i386 ?try_lock_for@critical_section@Concurrency@@QAE_NI@Z(ptr long) critical_section_try_lock_for +@ cdecl -arch=win64 ?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z(ptr long) critical_section_try_lock_for @ stub -arch=arm ?try_lock_read@reader_writer_lock@Concurrency@@QAA_NXZ @ stub -arch=i386 ?try_lock_read@reader_writer_lock@Concurrency@@QAE_NXZ @ stub -arch=win64 ?try_lock_read@reader_writer_lock@Concurrency@@QEAA_NXZ diff --git a/dlls/msvcrt/lock.c b/dlls/msvcrt/lock.c index 94599d196c0..aee8d2be45f 100644 --- a/dlls/msvcrt/lock.c +++ b/dlls/msvcrt/lock.c @@ -290,6 +290,10 @@ static HANDLE keyed_event; typedef struct cs_queue { struct cs_queue *next; +#if _MSVCR_VER >= 110 + BOOL free; + int unknown; +#endif } cs_queue; typedef struct @@ -298,7 +302,6 @@ typedef struct cs_queue unk_active; #if _MSVCR_VER >= 110 void *unknown[2]; - int unknown2[2]; #else void *unknown[1]; #endif @@ -373,7 +376,7 @@ void __thiscall critical_section_lock(critical_section *this) return; } - q.next = NULL; + memset(&q, 0, sizeof(q)); last = InterlockedExchangePointer(&this->tail, &q); if(last) { last->next = &q; @@ -400,7 +403,7 @@ MSVCRT_bool __thiscall critical_section_try_lock(critical_section *this) return FALSE; } - q.next = NULL; + 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) @@ -425,6 +428,23 @@ void __thiscall critical_section_unlock(critical_section *this) == &this->unk_active) return; spin_wait_for_next_cs(&this->unk_active); +#if _MSVCR_VER >= 110 + while(1) { + cs_queue *next; + + if(!InterlockedExchange(&this->unk_active.next->free, TRUE)) + break; + + next = this->unk_active.next; + if(InterlockedCompareExchangePointer(&this->tail, NULL, next) == next) + return; + spin_wait_for_next_cs(next); + + this->unk_active.next = next->next; + HeapFree(GetProcessHeap(), 0, next); + } +#endif + NtReleaseKeyedEvent(keyed_event, this->unk_active.next, 0, NULL); } @@ -437,6 +457,52 @@ critical_section* __thiscall critical_section_native_handle(critical_section *th return this; } +#if _MSVCR_VER >= 110 +/* ?try_lock_for@critical_section@Concurrency@@QAE_NI@Z */ +/* ?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z */ +DEFINE_THISCALL_WRAPPER(critical_section_try_lock_for, 8) +MSVCRT_bool __thiscall critical_section_try_lock_for( + critical_section *this, unsigned int timeout) +{ + cs_queue *q, *last; + + TRACE("(%p %d)\n", this, timeout); + + if(this->unk_thread_id == GetCurrentThreadId()) { + FIXME("throw exception\n"); + return FALSE; + } + + if(!(q = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*q)))) + return critical_section_try_lock(this); + + last = InterlockedExchangePointer(&this->tail, q); + if(last) { + LARGE_INTEGER to; + NTSTATUS status; + FILETIME ft; + + last->next = q; + GetSystemTimeAsFileTime(&ft); + to.QuadPart = ((LONGLONG)ft.dwHighDateTime<<32) + + ft.dwLowDateTime + (LONGLONG)timeout*10000; + status = NtWaitForKeyedEvent(keyed_event, q, 0, &to); + if(status == STATUS_TIMEOUT) { + if(!InterlockedExchange(&q->free, TRUE)) + return FALSE; + } + } + + 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); + HeapFree(GetProcessHeap(), 0, q); + return TRUE; +} +#endif + typedef struct { critical_section *cs;