msvcr110: Add critical_section::try_lock_for implementation.
This commit is contained in:
parent
7f23c57d09
commit
5175037b63
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue