Piotr Caban : msvcr110: Add critical_section::try_lock_for implementation.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Jun 24 14:28:33 CDT 2014
Module: wine
Branch: master
Commit: 5175037b635d638e16396bee7890e4512031f866
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5175037b635d638e16396bee7890e4512031f866
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue Jun 24 11:57:53 2014 +0200
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 57d7950..4127725 100644
--- a/dlls/msvcr110/msvcr110.spec
+++ b/dlls/msvcr110/msvcr110.spec
@@ -794,9 +794,9 @@
@ stub -arch=arm ?try_lock at reader_writer_lock@Concurrency@@QAA_NXZ
@ stub -arch=i386 ?try_lock at reader_writer_lock@Concurrency@@QAE_NXZ
@ stub -arch=win64 ?try_lock at reader_writer_lock@Concurrency@@QEAA_NXZ
-@ stub -arch=arm ?try_lock_for at critical_section@Concurrency@@QAA_NI at Z
-@ stub -arch=i386 ?try_lock_for at critical_section@Concurrency@@QAE_NI at Z
-@ stub -arch=win64 ?try_lock_for at critical_section@Concurrency@@QEAA_NI at Z
+@ cdecl -arch=arm ?try_lock_for at critical_section@Concurrency@@QAA_NI at Z(ptr long) critical_section_try_lock_for
+@ thiscall -arch=i386 ?try_lock_for at critical_section@Concurrency@@QAE_NI at Z(ptr long) critical_section_try_lock_for
+@ cdecl -arch=win64 ?try_lock_for at critical_section@Concurrency@@QEAA_NI at Z(ptr long) critical_section_try_lock_for
@ stub -arch=arm ?try_lock_read at reader_writer_lock@Concurrency@@QAA_NXZ
@ stub -arch=i386 ?try_lock_read at reader_writer_lock@Concurrency@@QAE_NXZ
@ stub -arch=win64 ?try_lock_read at reader_writer_lock@Concurrency@@QEAA_NXZ
diff --git a/dlls/msvcrt/lock.c b/dlls/msvcrt/lock.c
index 94599d1..aee8d2b 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 at critical_section@Concurrency@@QAE_NI at Z */
+/* ?try_lock_for at critical_section@Concurrency@@QEAA_NI at 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;
More information about the wine-cvs
mailing list