reactos/win32ss/gdi/eng/semaphor.c
David Quintana 057a69972f Sync with trunk r63174.
CORE-8176 #resolve #comment Trunk commit r63174 should fix this issue. I merged from trunk to bring it into Shell-experiments.

svn path=/branches/shell-experiments/; revision=63175
2014-05-06 15:51:24 +00:00

174 lines
3.5 KiB
C

#include <win32k.h>
#define NDEBUG
#include <debug.h>
/*
* @implemented
*/
HSEMAPHORE
APIENTRY
EngCreateSemaphore(VOID)
{
// www.osr.com/ddk/graphics/gdifncs_95lz.htm
PERESOURCE psem = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERESOURCE), GDITAG_SEMAPHORE);
if (!psem)
return NULL;
if (!NT_SUCCESS(ExInitializeResourceLite(psem)))
{
ExFreePoolWithTag ( psem, GDITAG_SEMAPHORE );
return NULL;
}
return (HSEMAPHORE)psem;
}
VOID
FASTCALL
IntGdiAcquireSemaphore(HSEMAPHORE hsem)
{
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite ((PERESOURCE)hsem, TRUE);
}
/*
* @implemented
*/
VOID
APIENTRY
EngAcquireSemaphore(IN HSEMAPHORE hsem)
{
// www.osr.com/ddk/graphics/gdifncs_14br.htm
PTHREADINFO W32Thread;
ASSERT(hsem);
IntGdiAcquireSemaphore(hsem);
W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
if (W32Thread) W32Thread->dwEngAcquireCount++;
}
VOID
FASTCALL
IntGdiReleaseSemaphore ( HSEMAPHORE hsem )
{
ExReleaseResourceLite((PERESOURCE)hsem);
KeLeaveCriticalRegion();
}
/*
* @implemented
*/
VOID
APIENTRY
EngReleaseSemaphore ( IN HSEMAPHORE hsem )
{
// www.osr.com/ddk/graphics/gdifncs_5u3r.htm
PTHREADINFO W32Thread;
ASSERT(hsem);
W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
if (W32Thread) --W32Thread->dwEngAcquireCount;
IntGdiReleaseSemaphore(hsem);
}
VOID
NTAPI
EngAcquireSemaphoreShared(
IN HSEMAPHORE hsem)
{
PTHREADINFO pti;
ASSERT(hsem);
ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
pti = PsGetThreadWin32Thread(PsGetCurrentThread());
if (pti) ++pti->dwEngAcquireCount;
}
/*
* @implemented
*/
VOID
APIENTRY
EngDeleteSemaphore ( IN HSEMAPHORE hsem )
{
// www.osr.com/ddk/graphics/gdifncs_13c7.htm
ASSERT(hsem);
ExDeleteResourceLite((PERESOURCE)hsem);
ExFreePoolWithTag((PVOID)hsem, GDITAG_SEMAPHORE);
}
/*
* @implemented
*/
BOOL
APIENTRY
EngIsSemaphoreOwned ( IN HSEMAPHORE hsem )
{
// www.osr.com/ddk/graphics/gdifncs_6wmf.htm
ASSERT(hsem);
return (((PERESOURCE)hsem)->ActiveCount > 0);
}
/*
* @implemented
*/
BOOL
APIENTRY
EngIsSemaphoreOwnedByCurrentThread ( IN HSEMAPHORE hsem )
{
// www.osr.com/ddk/graphics/gdifncs_9yxz.htm
ASSERT(hsem);
return ExIsResourceAcquiredExclusiveLite((PERESOURCE)hsem);
}
/*
* @implemented
*/
BOOL APIENTRY
EngInitializeSafeSemaphore(
OUT ENGSAFESEMAPHORE *Semaphore)
{
HSEMAPHORE hSem;
if (InterlockedIncrement(&Semaphore->lCount) == 1)
{
/* Create the semaphore */
hSem = EngCreateSemaphore();
if (hSem == 0)
{
InterlockedDecrement(&Semaphore->lCount);
return FALSE;
}
/* FIXME: Not thread-safe! Check result of InterlockedCompareExchangePointer
and delete semaphore if already initialized! */
(void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem);
}
else
{
/* Wait for the other thread to create the semaphore */
ASSERT(Semaphore->lCount > 1);
ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
while (Semaphore->hsem == NULL);
}
return TRUE;
}
/*
* @implemented
*/
VOID APIENTRY
EngDeleteSafeSemaphore(
IN OUT ENGSAFESEMAPHORE *Semaphore)
{
if (InterlockedDecrement(&Semaphore->lCount) == 0)
{
/* FIXME: Not thread-safe! Use result of InterlockedCompareExchangePointer! */
EngDeleteSemaphore(Semaphore->hsem);
(void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, NULL);
}
}
/* EOF */