reupload this
This commit is contained in:
280
condvar.c
Normal file
280
condvar.c
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "progwrp.h"
|
||||
#include "export.h"
|
||||
#include "implementations.h"
|
||||
|
||||
#define SEMAPHORE_BIT (1 << 31)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PULONG CondVarBitMasks;
|
||||
ULONG NumberBitMasks;
|
||||
}COND_VAR_BASE, * PCOND_VAR_BASE;
|
||||
|
||||
|
||||
NTSYSAPI PVOID RtlAllocateHeap(
|
||||
PVOID HeapHandle,
|
||||
ULONG Flags,
|
||||
SIZE_T Size
|
||||
);
|
||||
|
||||
NTSYSAPI VOID RtlFreeHeap(
|
||||
PVOID HeapHandle,
|
||||
ULONG Flags,
|
||||
PVOID BaseAddress
|
||||
);
|
||||
|
||||
#define RtlMoveMemory RtlMoveMemory
|
||||
|
||||
VOID NTAPI RtlMoveMemory(
|
||||
PVOID Destination,
|
||||
PVOID Source,
|
||||
SIZE_T Length
|
||||
);
|
||||
|
||||
/*
|
||||
A condition variable is a synchronization object which allows many
|
||||
threads to synchronize on one variable, in a pseudo-queue.
|
||||
|
||||
I determined that the condition variable could consist of an expandable array of bit masks.
|
||||
One bit mask has two bits per thread; one to indicate that the section of the bit mask is in use
|
||||
and another to indicate that the bit mask has been signalled.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
HANDLE SingleWakeEvent;
|
||||
HANDLE AllWakeEvent;
|
||||
HANDLE AccessSemaphore;
|
||||
ULONG WaiterCount;
|
||||
}CONDITION_VARIABLE_INT, * PCONDITION_VARIABLE_INT;
|
||||
|
||||
BOOL WINAPI Implementation_SleepConditionVariableSRW(
|
||||
PCONDITION_VARIABLE ConditionVariable,
|
||||
PSRWLOCK SRWLock,
|
||||
DWORD dwMilliseconds,
|
||||
ULONG Flags
|
||||
)
|
||||
{
|
||||
int i;
|
||||
DWORD dwWaitStatus;
|
||||
DWORD dwCondVarIdx;
|
||||
PTEB_CUSTOM Teb;
|
||||
PCONDITION_VARIABLE_INT pCondVar;
|
||||
|
||||
if (!(!SRWLock && Flags == 2)) {
|
||||
|
||||
if (!ConditionVariable || !SRWLock || Flags & ~(CONDITION_VARIABLE_LOCKMODE_SHARED))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Teb = (PTEB_CUSTOM)NtCurrentTeb();
|
||||
|
||||
if (!ConditionVariable->Ptr)
|
||||
{
|
||||
pCondVar = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONDITION_VARIABLE_INT));
|
||||
if (!pCondVar)
|
||||
return FALSE;
|
||||
#ifdef _M_X64
|
||||
if (InterlockedCompareExchange64(ConditionVariable, pCondVar, 0))
|
||||
#else
|
||||
if (InterlockedCompareExchange(ConditionVariable, pCondVar, 0))
|
||||
#endif
|
||||
HeapFree(GetProcessHeap(), 0, pCondVar);
|
||||
else
|
||||
{
|
||||
pCondVar->WaiterCount = 0;
|
||||
pCondVar->AccessSemaphore = CreateSemaphoreA(NULL, 1, 1, NULL);
|
||||
pCondVar->AllWakeEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
pCondVar->SingleWakeEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
pCondVar = ConditionVariable->Ptr;
|
||||
|
||||
WaitForSingleObject(pCondVar->AccessSemaphore, INFINITE);
|
||||
|
||||
InterlockedIncrement(&pCondVar->WaiterCount);
|
||||
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
|
||||
if (Flags & CONDITION_VARIABLE_LOCKMODE_SHARED)
|
||||
Implementation_ReleaseSRWLockShared(SRWLock);
|
||||
else
|
||||
Implementation_ReleaseSRWLockExclusive(SRWLock);
|
||||
|
||||
|
||||
HANDLE MultipleHandles[2] = { pCondVar->AllWakeEvent, pCondVar->SingleWakeEvent };
|
||||
dwWaitStatus = WaitForMultipleObjects(2, MultipleHandles, FALSE, dwMilliseconds);
|
||||
|
||||
if (!InterlockedDecrement(&pCondVar->WaiterCount)) {
|
||||
ResetEvent(pCondVar->AllWakeEvent);
|
||||
ResetEvent(pCondVar->SingleWakeEvent);
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
}
|
||||
else if (dwWaitStatus == WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (Flags & CONDITION_VARIABLE_LOCKMODE_SHARED)
|
||||
Implementation_AcquireSRWLockShared(SRWLock);
|
||||
else
|
||||
Implementation_AcquireSRWLockExclusive(SRWLock);
|
||||
|
||||
if (dwWaitStatus != WAIT_OBJECT_0 &&
|
||||
dwWaitStatus != WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI Implementation_SleepConditionVariableCS(
|
||||
PCONDITION_VARIABLE ConditionVariable,
|
||||
PCRITICAL_SECTION CriticalSection,
|
||||
DWORD dwMilliseconds
|
||||
)
|
||||
{
|
||||
int i;
|
||||
DWORD dwWaitStatus;
|
||||
DWORD dwCondVarIdx;
|
||||
PTEB_CUSTOM Teb;
|
||||
PCONDITION_VARIABLE_INT pCondVar;
|
||||
|
||||
if (!ConditionVariable || !CriticalSection)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!ConditionVariable->Ptr)
|
||||
{
|
||||
pCondVar = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONDITION_VARIABLE_INT));
|
||||
|
||||
#ifdef _M_X64
|
||||
if (InterlockedCompareExchange64(ConditionVariable, pCondVar, 0))
|
||||
#else
|
||||
if (InterlockedCompareExchange(ConditionVariable, pCondVar, 0))
|
||||
#endif
|
||||
HeapFree(GetProcessHeap(), 0, pCondVar);
|
||||
else
|
||||
{
|
||||
pCondVar->WaiterCount = 0;
|
||||
pCondVar->AccessSemaphore = CreateSemaphoreA(NULL, 1, 1, NULL);
|
||||
pCondVar->AllWakeEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
pCondVar->SingleWakeEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
pCondVar = ConditionVariable->Ptr;
|
||||
|
||||
WaitForSingleObject(pCondVar->AccessSemaphore, INFINITE);
|
||||
|
||||
InterlockedIncrement(&pCondVar->WaiterCount);
|
||||
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
|
||||
LeaveCriticalSection(CriticalSection);
|
||||
HANDLE MultipleHandles[2] = { pCondVar->AllWakeEvent, pCondVar->SingleWakeEvent };
|
||||
dwWaitStatus = WaitForMultipleObjects(2, MultipleHandles, FALSE, dwMilliseconds);
|
||||
|
||||
if (!InterlockedDecrement(&pCondVar->WaiterCount)) {
|
||||
ResetEvent(pCondVar->AllWakeEvent);
|
||||
ResetEvent(pCondVar->SingleWakeEvent);
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
}
|
||||
else if (dwWaitStatus == WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
}
|
||||
|
||||
EnterCriticalSection(CriticalSection);
|
||||
SetLastError(dwWaitStatus);
|
||||
if (dwWaitStatus != WAIT_OBJECT_0 &&
|
||||
dwWaitStatus != WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void WINAPI Implementation_InitializeConditionVariable(
|
||||
PCONDITION_VARIABLE ConditionVariable
|
||||
)
|
||||
{
|
||||
ConditionVariable->Ptr = 0;
|
||||
}
|
||||
|
||||
typedef struct _THREAD_BASIC_INFORMATION {
|
||||
NTSTATUS ExitStatus;
|
||||
PVOID TebBaseAddress;
|
||||
CLIENT_ID ClientId;
|
||||
KAFFINITY AffinityMask;
|
||||
KPRIORITY Priority;
|
||||
KPRIORITY BasePriority;
|
||||
} THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _OBJECT_BASIC_INFORMATION {
|
||||
ULONG Attributes;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG HandleCount;
|
||||
ULONG PointerCount;
|
||||
ULONG PagedPoolCharge;
|
||||
ULONG NonPagedPoolCharge;
|
||||
ULONG Reserved[3];
|
||||
ULONG NameInfoSize;
|
||||
ULONG TypeInfoSize;
|
||||
ULONG SecurityDescriptorSize;
|
||||
LARGE_INTEGER CreationTime;
|
||||
} OBJECT_BASIC_INFORMATION, * POBJECT_BASIC_INFORMATION;
|
||||
|
||||
|
||||
void WINAPI Implementation_WakeConditionVariable(
|
||||
PCONDITION_VARIABLE ConditionVariable
|
||||
)
|
||||
{
|
||||
if (ConditionVariable)
|
||||
{
|
||||
PCONDITION_VARIABLE_INT pCondVar = ConditionVariable->Ptr;
|
||||
if (ConditionVariable->Ptr) {
|
||||
WaitForSingleObject(pCondVar->AccessSemaphore, INFINITE);
|
||||
if (!pCondVar->WaiterCount) {
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
}
|
||||
else {
|
||||
SetEvent(pCondVar->SingleWakeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WINAPI Implementation_WakeAllConditionVariable(
|
||||
PCONDITION_VARIABLE ConditionVariable
|
||||
)
|
||||
{
|
||||
if (ConditionVariable)
|
||||
{
|
||||
PCONDITION_VARIABLE_INT pCondVar = ConditionVariable->Ptr;
|
||||
if (ConditionVariable->Ptr) {
|
||||
WaitForSingleObject(pCondVar->AccessSemaphore, INFINITE);
|
||||
if (!pCondVar->WaiterCount) {
|
||||
ReleaseSemaphore(pCondVar->AccessSemaphore, 1, NULL);
|
||||
}
|
||||
else {
|
||||
SetEvent(pCondVar->AllWakeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user