📄 schedule.c
字号:
DEBUGMSG(ZONE_ENTRY,(L"SC_EventGetData entry: %8.8lx\r\n",hEvent));
if (!(lpe = HandleToEventPerm(hEvent))) {
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
DEBUGMSG(ZONE_ENTRY,(L"SC_EventGetData exit: -1\r\n"));
return 0;
}
if (!lpe->dwData) {
KSetLastError (pCurThread, 0); // no error
}
DEBUGMSG(ZONE_ENTRY,(L"SC_EventGetData exit: %8.8lx\r\n", lpe->dwData));
return lpe->dwData;
}
/* When a thread tries to set/reset/pulse an event */
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_EventModify(
HANDLE hEvent,
DWORD type
)
{
LPEVENT lpe;
HANDLE hWake;
LPSTUBEVENT lpse;
DEBUGMSG(ZONE_ENTRY,(L"SC_EventModify entry: %8.8lx %8.8lx\r\n",hEvent,type));
if (!(lpe = HandleToEventPerm(hEvent))) {
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
return FALSE;
}
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CELOG_Event(hEvent, type);
}
switch (type) {
case EVENT_PULSE:
case EVENT_SET:
if (lpe->pIntrProxy) {
DEBUGCHK(lpe->onequeue);
if (hWake = (HANDLE)KCall((PKFN)EventModIntr,lpe,type))
KCall((PKFN)MakeRunIfNeeded,hWake);
} else if (lpe->manualreset) {
DWORD dwOldPrio, dwNewPrio;
DEBUGCHK(lpe->onequeue);
// *lpse can't be stack-based since other threads won't have access and might dequeue/requeue
if (!(lpse = AllocMem(HEAP_STUBEVENT))) {
DEBUGMSG(ZONE_ENTRY,(L"SC_EventModify exit: %8.8lx\r\n",FALSE));
KSetLastError(pCurThread,ERROR_OUTOFMEMORY);
return FALSE;
}
dwOldPrio = GET_BPRIO(pCurThread);
dwNewPrio = KCall((PKFN)EventModMan,lpe,lpse,type);
if (lpse->pProxList) {
SET_NOPRIOCALC(pCurThread);
if (dwNewPrio < dwOldPrio)
SET_CPRIO(pCurThread,dwNewPrio);
while (lpse->pProxList) {
hWake = 0;
KCall((PKFN)WakeOneThreadFlat,lpse,&hWake);
if (hWake)
KCall((PKFN)MakeRunIfNeeded,hWake);
}
CLEAR_NOPRIOCALC(pCurThread);
if (dwNewPrio < dwOldPrio)
KCall((PKFN)AdjustPrioDown);
}
FreeMem(lpse,HEAP_STUBEVENT);
} else {
hWake = 0;
while (KCall((PKFN)EventModAuto,lpe,type,&hWake))
;
if (hWake)
KCall((PKFN)MakeRunIfNeeded,hWake);
}
break;
case EVENT_RESET:
lpe->state = 0;
break;
default:
DEBUGCHK(0);
}
DEBUGMSG(ZONE_ENTRY,(L"SC_EventModify exit: %8.8lx\r\n",TRUE));
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
IsValidIntrEvent(
HANDLE hEvent
)
{
EVENT *lpe;
if (!(lpe = HandleToEvent(hEvent)) || lpe->manualreset || lpe->pProxList)
return FALSE;
return TRUE;
}
typedef DWORD (* PFN_InitSyncObj) (HANDLE hObj, LPVOID pObj, DWORD dwParam1, DWORD dwParam2, LPName pName);
typedef void (* PFN_DeInitSyncObj) (HANDLE hObj, LPVOID pObj);
typedef LPName (* PFN_GetName) (LPVOID pObj);
//
// structure to define object specific methods of kernel sync-objects (mutex, event, and semaphore)
// NOTE: name comparision is object specific because it's not at the same offset
// for individual objects. We should probabaly look into changing the structures
// so they're at the same offset and then we don't need a compare-name method.
//
typedef struct _SYNCOBJ_METHOD {
PFN_InitSyncObj pfnInit;
PFN_DeInitSyncObj pfnDeInit;
PFN_GetName pfnGetName;
const CINFO *pci;
LPCRITICAL_SECTION lpcs;
} SYNCOBJ_METHOD, *PSYNCOBJ_METHOD;
//------------------------------------------------------------------------------
// initialize a mutex
//------------------------------------------------------------------------------
static DWORD InitMutex (HANDLE hObj, LPVOID pObj, DWORD bInitialOwner, DWORD unused, LPName pName)
{
LPMUTEX pMutex = (LPMUTEX) pObj;
pMutex->name = pName;
if (bInitialOwner) {
pMutex->LockCount = 1;
pMutex->pOwner = pCurThread;
KCall ((PKFN)LaterLinkCritMut, pMutex, 0);
}
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CELOG_MutexCreate(hObj, pMutex);
}
return 0; // no error
}
//------------------------------------------------------------------------------
// initialize an event
//------------------------------------------------------------------------------
static DWORD InitEvent (HANDLE hObj, LPVOID pObj, DWORD fManualReset, DWORD fInitState, LPName pName)
{
LPEVENT pEvent = (LPEVENT) pObj;
pEvent->name = pName;
pEvent->state = (BYTE) fInitState;
pEvent->manualreset = pEvent->onequeue = (BYTE) fManualReset;
pEvent->bMaxPrio = THREAD_RT_PRIORITY_IDLE;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CELOG_EventCreate(hObj, fManualReset, fInitState, pName? pName->name : NULL, TRUE);
}
return 0; // no error
}
//------------------------------------------------------------------------------
// initialize a semaphore
//------------------------------------------------------------------------------
static DWORD InitSemaphore (HANDLE hObj, LPVOID pObj, DWORD lInitCount, DWORD lMaxCount, LPName pName)
{
LPSEMAPHORE pSem = (LPSEMAPHORE) pObj;
if (((LONG) lInitCount < 0) || ((LONG) lMaxCount < 0) || (lInitCount > lMaxCount))
return ERROR_INVALID_PARAMETER;
pSem->name = pName;
pSem->lMaxCount = (LONG) lMaxCount;
pSem->lCount = (LONG) lInitCount;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CELOG_SemaphoreCreate(hObj, (LONG) lInitCount, (LONG) lMaxCount, pName? pName->name : NULL);
}
return 0; // no error
}
//------------------------------------------------------------------------------
// delete a mutex
//------------------------------------------------------------------------------
static void DeInitMutex (HANDLE hObj, LPVOID pObj)
{
LPMUTEX pMutex = (LPMUTEX) pObj;
BOOL fOtherWaiting = FALSE;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
CELOG_MutexDelete (hObj);
}
while (pMutex->pProxList) {
if (KCall ((PKFN)DequeuePrioProxy, pMutex->pProxList)) {
KCall ((PKFN)DoReprioMutex, pMutex);
fOtherWaiting = TRUE;
}
}
KCall ((PKFN)DoFreeMutex, pMutex);
if (pMutex->name)
FreeName (pMutex->name);
DEBUGMSG (fOtherWaiting, (L"WARNING: Mutex %8.8lx is deleted while other thread is waiting for it\r\n", hObj));
DEBUGCHK (!fOtherWaiting);
}
//------------------------------------------------------------------------------
// delete an event
//------------------------------------------------------------------------------
static void DeInitEvent (HANDLE hObj, LPVOID pObj)
{
LPEVENT pEvent = (LPEVENT) pObj;
PKFN pfnDequeue = pEvent->onequeue? (PKFN) DequeueFlatProxy : (PKFN) DequeuePrioProxy;
BOOL fOtherWaiting = FALSE;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
CELOG_EventDelete (hObj);
}
// delete the watchdog object if this is a watchdog event
if (pEvent->dwData) {
WDDelete (hObj);
}
while (pEvent->pProxList) {
if (KCall (pfnDequeue, pEvent->pProxList))
fOtherWaiting = TRUE;
}
if (pEvent->name)
FreeName (pEvent->name);
if (pEvent->pIntrProxy)
FreeIntrFromEvent (pEvent);
DEBUGMSG (fOtherWaiting, (L"WARNING: Event %8.8lx is deleted while other thread is waiting for it\r\n", hObj));
}
//------------------------------------------------------------------------------
// delete a semaphore
//------------------------------------------------------------------------------
static void DeInitSemaphore (HANDLE hObj, LPVOID pObj)
{
LPSEMAPHORE pSem = (LPSEMAPHORE) pObj;
BOOL fOtherWaiting = FALSE;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
CELOG_SemaphoreDelete (hObj);
}
while (pSem->pProxList) {
if (KCall ((PKFN)DequeuePrioProxy, pSem->pProxList))
fOtherWaiting = TRUE;
}
if (pSem->name)
FreeName (pSem->name);
DEBUGMSG (fOtherWaiting, (L"WARNING: Semaphore %8.8lx is deleted while other thread is waiting for it\r\n", hObj));
}
//------------------------------------------------------------------------------
// get name of a mutex
//------------------------------------------------------------------------------
static LPName MutexGetName (LPVOID pObj)
{
return ((LPMUTEX) pObj)->name;
}
//------------------------------------------------------------------------------
// get name of a event
//------------------------------------------------------------------------------
static LPName EventGetName (LPVOID pObj)
{
return ((LPEVENT) pObj)->name;
}
//------------------------------------------------------------------------------
// get name of a semaphore
//------------------------------------------------------------------------------
static LPName SemGetName (LPVOID pObj)
{
return ((LPSEMAPHORE) pObj)->name;
}
//
// Event methods
//
static SYNCOBJ_METHOD eventMethod = {
InitEvent,
DeInitEvent,
EventGetName,
&cinfEvent,
&EventCS,
};
//
// Mutex methods
//
static SYNCOBJ_METHOD mutexMethod = {
InitMutex,
DeInitMutex,
MutexGetName,
&cinfMutex,
&MutexCS,
};
//
// Semaphore methods
//
static SYNCOBJ_METHOD semMethod = {
InitSemaphore,
DeInitSemaphore,
SemGetName,
&cinfSem,
&SemCS,
};
//------------------------------------------------------------------------------
// common function to create/open a sync-object
//------------------------------------------------------------------------------
static HANDLE OpenOrCreateSyncObject (
LPSECURITY_ATTRIBUTES lpsa,
DWORD dwParam1,
DWORD dwParam2,
LPCWSTR pszName,
HANDLE *phHandleList,
PSYNCOBJ_METHOD pObjMethod,
BOOL fCreate)
{
int len = 0;
DWORD dwErr = 0;
HANDLE hObj = NULL;
LPVOID pObj;
DWORD dwSavedLastErr = KGetLastError (pCurThread);
// error if open existing without a name
if (!fCreate && !pszName) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return NULL;
}
// validate parameters
if (pszName) {
// caller needs to be trusted if the named object is system prefixed (case insensitive)
if (!kstrncmpi (pszName, TEXT("SYSTEM/"), 7)) {
TRUSTED_API (L"OpenOrCreateSyncObject", NULL);
}
// try to find it in the list if name is supplied
len = strlenW(pszName) + 1;
if ((MAX_PATH < len) || !LockPages(pszName, len *= sizeof(WCHAR), 0, LOCKFLAG_READ)) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return NULL;
}
}
EnterCriticalSection(pObjMethod->lpcs);
// try to find if name exists
if (pszName) {
for (hObj = *phHandleList; hObj; hObj = ((LPEVENT) pObj)->hNext) {
LPName pObjName;
pObj = GetObjectPtrByType (hObj, pObjMethod->pci->type);
DEBUGCHK (pObj);
pObjName = pObjMethod->pfnGetName (pObj);
if (pObjName && !strcmpW (pObjName->name, pszName)) {
// object already exist,
if (ACLCheck (hObj)) {
// increment ref-count and done
IncRef (hObj, pCurProc);
dwErr = ERROR_ALREADY_EXISTS;
} else {
// no access
dwErr = ERROR_ACCESS_DENIED;
hObj = NULL;
}
break;
}
}
}
// error if open existing but not found
if (!fCreate && !hObj && !dwErr) {
dwErr = ERROR_FILE_NOT_FOUND;
} else if (!dwErr) {
dwSavedLastErr = 0;
}
if (!dwErr) {
// create a new object
LPName pName = NULL, psd = NULL;
if ((pObj = AllocMem (HEAP_SYNC_OBJ))
&& (hObj = AllocHandle (pObjMethod->pci, pObj, pCurProc))
&& (!len || (pName = AllocName (len)))
&& (!lpsa || !(dwErr = AllocPSD (lpsa, &psd)))) {
// clear memory
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -