mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
2.9 KiB
130 lines
2.9 KiB
/* sem.c -- simple semaphores. */
|
|
/* Copyright 1995 Spyglass, Inc. All Rights Reserved. */
|
|
/* Jeff Hostetler, Spyglass, Inc. 1995. */
|
|
|
|
#include "all.h"
|
|
|
|
#define STATE_SEM_GOTSEMAPHORE (STATE_OTHER + 0)
|
|
|
|
|
|
Sem gModalDialogSemaphore;
|
|
|
|
|
|
void Sem_InitSem(Sem * sem)
|
|
{
|
|
memset((void *)sem,0,sizeof(*sem));
|
|
return;
|
|
}
|
|
|
|
BOOL Sem_CondWaitSem_Sync(Sem * sem)
|
|
{
|
|
/* conditionally take lock on simple semaphore object.
|
|
* (take lock if we can do so without blocking)
|
|
*
|
|
* Return TRUE iff we took the lock.
|
|
* Return FALSE if error or already locked.
|
|
*
|
|
*/
|
|
|
|
if (!sem)
|
|
return FALSE;
|
|
|
|
if (sem->bLocked)
|
|
return FALSE;
|
|
|
|
XX_Assert((sem->qHead==0),("Sem_WaitSem_Sync: qHead not zero -- not locked, but someone waiting...."));
|
|
|
|
sem->bLocked = TRUE;
|
|
XX_DMsg(DBG_SEM,("Sem_CondWaitSem_Sync: Taking Semaphore [0x%08lx]\n",sem));
|
|
return TRUE;
|
|
}
|
|
|
|
void Sem_SignalSem_Sync(Sem * sem)
|
|
{
|
|
/* release current lock on the given semaphore.
|
|
* if a thread is waiting, unblock the thread and give it the lock.
|
|
*/
|
|
|
|
if (!sem)
|
|
return;
|
|
|
|
if (!sem->bLocked)
|
|
return;
|
|
|
|
if (sem->qHead)
|
|
{
|
|
SemQueueEntry * sqe = sem->qHead;
|
|
|
|
XX_DMsg(DBG_SEM,("Sem_SignalSem_Sync: Giving Semaphore [0x%08lx] to window [%d]\n",sem,sqe->tw));
|
|
Async_UnblockByWindow(sqe->tw); /* release current threads */
|
|
if (sem->qTail == sqe)
|
|
{
|
|
XX_Assert((sqe->qNext==0),("Sem_SignalSem_Sync: qNext not zero -- when head == tail...."));
|
|
sem->qTail = sqe->qNext;
|
|
}
|
|
|
|
sem->qHead = sqe->qNext;
|
|
GTR_FREE(sqe);
|
|
}
|
|
|
|
/* no threads waiting */
|
|
|
|
sem->bLocked = FALSE;
|
|
XX_DMsg(DBG_SEM,("Sem_SignalSem_Sync: Releasing Semaphore [0x%08lx]\n",sem));
|
|
return;
|
|
}
|
|
|
|
int Sem_WaitSem_Async(struct Mwin * tw, int nState, void **ppInfo)
|
|
{
|
|
/* must be called from a thread context */
|
|
|
|
struct Params_SemData * pSemData = *ppInfo;
|
|
SemQueueEntry * sqe;
|
|
|
|
switch (nState)
|
|
{
|
|
case STATE_INIT:
|
|
if (tw == NULL)
|
|
{
|
|
*pSemData->pStatus = 0;
|
|
return STATE_DONE;
|
|
}
|
|
if (Sem_CondWaitSem_Sync(pSemData->semaphore))
|
|
{
|
|
/* no one holding it or in the queue waiting for
|
|
* it, so we just took it without blocking.
|
|
*/
|
|
*pSemData->pStatus = 1;
|
|
return STATE_DONE;
|
|
}
|
|
|
|
/* add us to end of FIFO waiting on this semaphore */
|
|
|
|
sqe = GTR_CALLOC(1,sizeof(*sqe));
|
|
if (!sqe)
|
|
{
|
|
*pSemData->pStatus = 0;
|
|
return STATE_DONE;
|
|
}
|
|
sqe->tw = tw;
|
|
if (pSemData->semaphore->qTail)
|
|
pSemData->semaphore->qTail->qNext = sqe;
|
|
pSemData->semaphore->qTail = sqe;
|
|
if (!pSemData->semaphore->qHead)
|
|
pSemData->semaphore->qHead = sqe;
|
|
Async_BlockByWindow(sqe->tw);
|
|
|
|
XX_DMsg(DBG_SEM,("Sem_WaitSem_Async: Queueing Window [%d] for Semaphore [0x%08lx]\n",sqe->tw,pSemData->semaphore));
|
|
return STATE_SEM_GOTSEMAPHORE;
|
|
|
|
case STATE_SEM_GOTSEMAPHORE:
|
|
*pSemData->pStatus = 1;
|
|
return STATE_DONE;
|
|
|
|
case STATE_ABORT:
|
|
*pSemData->pStatus = 0;
|
|
return STATE_DONE;
|
|
}
|
|
XX_Assert((0), ("Function called with illegal state: %d", nState));
|
|
return STATE_DONE;
|
|
}
|