reactos/subsystems/win32/win32k/eng/semaphor.c
Jérôme Gardou 88c9e7c6e8 Sync with trunk (r47116), hopefully without breaking anything.
svn path=/branches/reactos-yarotows/; revision=47117
2010-05-07 07:41:13 +00:00

172 lines
3.4 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), TAG_GSEM );
if ( !psem )
return NULL;
if ( !NT_SUCCESS(ExInitializeResourceLite ( psem )) )
{
ExFreePoolWithTag ( psem, TAG_GSEM );
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, TAG_GSEM);
}
/*
* @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);
}
}