void* DeviceThread (void* pArg) { DEVTHREADPARMS* pThreadParms; // ptr to thread parms LIST_ENTRY* pListEntry; // (work) DEVIOREQUEST* pIORequest; // ptr to i/o request void* pDevBlk; // ptr to device block int* pnDevPrio; // ptr to device i/o priority int nCurPrio; // current thread priority pThreadParms = (DEVTHREADPARMS*) pArg; pThreadParms->dwThreadID = GetCurrentThreadId(); nCurPrio = getpriority(PRIO_PROCESS, 0); AdjustThreadPriority(&nCurPrio,ios_devthread_prio); for (;;) { // Wait for an i/o request to be queued... InterlockedIncrement(&ios_devtwait); MyWaitForSingleObject(pThreadParms->hRequestQueuedEvent,ios_devthread_timeout * 1000); InterlockedDecrement(&ios_devtwait); if (IsEventSet(pThreadParms->hShutdownEvent)) break; // Lock our queue so it doesn't change while we take a look at it... LockThreadParms(pThreadParms); // (freeze moving target) // Check to see if we have any work... if (IsListEmpty(&pThreadParms->IORequestListHeadListEntry)) { // We've waited long enough... pThreadParms->bThreadIsDead = TRUE; // (keep scheduler informed) UnlockThreadParms(pThreadParms); // (let go of our parms block) return NULL; // (return, NOT break!) } // Remove the i/o request from our queue... // It's important that we remove the request from our queue but // NOT reset our flag (if the list is now empty) until AFTER we've // processed the request (see further below for details as to why). pListEntry = RemoveListHead(&pThreadParms->IORequestListHeadListEntry); UnlockThreadParms(pThreadParms); // (done with thread parms for now) pIORequest = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); pDevBlk = pIORequest->pDevBlk; // (need ptr to devblk) pnDevPrio = pIORequest->pnDevPrio; // (need ptr to devprio) free(pIORequest); // (not needed anymore) // Process the i/o request by calling the proper 'execute_ccw_chain' // function (based on architectural mode) in source module channel.c // Set thread priority to requested device level AdjustThreadPriority(&nCurPrio,pnDevPrio); call_execute_ccw_chain(ios_arch_mode, pDevBlk); // (process i/o request) // Reset thread priority, if necessary if (nCurPrio > *ios_devthread_prio) AdjustThreadPriority(&nCurPrio,ios_devthread_prio); //////////////////////////////////////////////////////////////////////////// // // * * * I M P O R T A N T * * * // // It's important that we reset our flag AFTER we're done with our request // in order to prevent the scheduler from trying to give us more work while // we're still busy processing the current i/o request (in case the channel // program we're processing gets suspended). If the channel program we're // processing gets suspended and the scheduler places another request in our // queue, it won't ever get processed until our suspended channel program is // resumed, and if the request that was placed in our queue was a request // for an i/o to another device that the operating system needs to complete // in order to obtain the information needed to resume our suspended channel // program, a deadlock will occur! (i.e. if the operating system needs to // read data from another device before it can resume our channel program, // then the i/o request to read from that device better not be given to us // because we're suspended and will never get around to executing it until // we're resumed, which will never happen until the i/o request waiting in // our queue is completed, which will never happend until we're resumed, // etc...) // //////////////////////////////////////////////////////////////////////////// // Now that we're done this i/o, reset our flag. LockThreadParms(pThreadParms); // (freeze moving target) if (IsListEmpty(&pThreadParms->IORequestListHeadListEntry)) MyResetEvent(pThreadParms->hRequestQueuedEvent); UnlockThreadParms(pThreadParms); // (thaw moving target) if (IsEventSet(pThreadParms->hShutdownEvent)) break; // If we're a "one time only" thread, then we're done. if (ios_devtmax < 0) { // Note: no need to lock our thread parms before setting 'dead' flag // since the scheduler should never queue us another request anyway // because we're a "one-time-only" thread. pThreadParms->bThreadIsDead = TRUE; // (let garbage collector discard us) return NULL; // (return, NOT break!) } } // The only time we reach here is if the shutdown event was signalled (i.e. we // were manually "cancelled" or asked to stop processing; i.e. the i/o subsystem // was reset). Discard all i/o requests that may still be remaining in our queue. TRACE("** DeviceThread %8.8X: shutdown detected\n", (unsigned int)pThreadParms->dwThreadID); LockThreadParms(pThreadParms); // (freeze moving target) // Discard all queued i/o requests... while (!IsListEmpty(&pThreadParms->IORequestListHeadListEntry)) { pListEntry = RemoveListHead(&pThreadParms->IORequestListHeadListEntry); pIORequest = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); TRACE("** DeviceThread %8.8X: discarding i/o request for device %4.4X\n", (unsigned int)pThreadParms->dwThreadID,pIORequest->wDevNum); free(pIORequest); } pThreadParms->bThreadIsDead = TRUE; // (tell scheduler we've died) TRACE("** DeviceThread %8.8X: shutdown complete\n", (unsigned int)pThreadParms->dwThreadID); UnlockThreadParms(pThreadParms); // (thaw moving target) return NULL; }
static IMG_VOID LayoutCfgFromCtrlDepNode(PINTERMEDIATE_STATE psState, PCTRL_DEP_NODE psCtrlDepNode, PCFG psCfg, PCODEBLOCK* ppsEntryBlock, PCODEBLOCK* ppsExitBlock, PCODEBLOCK psCfgActualExitBlock, IMG_BOOL bDuplicateCodeBlocks) { if (psCtrlDepNode->eCtrlDepType == CTRL_DEP_TYPE_BLOCK) { if (bDuplicateCodeBlocks == IMG_FALSE) { IMG_UINT32 uLstNodesCount = GetListNodesCount(&(psCtrlDepNode->u.sBlock.sPredLst)); if (uLstNodesCount > 1) { PUSC_LIST_ENTRY psListEntry = RemoveListHead(&(psCtrlDepNode->u.sBlock.sPredLst)); PCTRL_DEP_NODE_LISTENTRY psCtrlDepNodeLstEntry; psCtrlDepNodeLstEntry = IMG_CONTAINING_RECORD(psListEntry, PCTRL_DEP_NODE_LISTENTRY, sListEntry); UscFree(psState, psCtrlDepNodeLstEntry); //printf("duplication needed\n"); bDuplicateCodeBlocks = IMG_TRUE; } } if (psCtrlDepNode->u.sBlock.uNumSucc == 0) { if (psCtrlDepNode->u.sBlock.psBlock != psCfgActualExitBlock) { (*ppsExitBlock) = (*ppsEntryBlock) = DuplicateCodeBlockIfNeeded(psState, bDuplicateCodeBlocks, psCtrlDepNode->u.sBlock.psBlock); } else { PCODEBLOCK psReturnBlock; PINST psReturnInst; psReturnBlock = AllocateBlock(psState, psCfg); psReturnInst = AllocateInst(psState, NULL); SetOpcodeAndDestCount(psState, psReturnInst, IRETURN, 0); AppendInst(psState, psReturnBlock, psReturnInst); (*ppsExitBlock) = (*ppsEntryBlock) = psReturnBlock; } } else if (psCtrlDepNode->u.sBlock.uNumSucc == 1) { PCODEBLOCK psSubCfgEntryBlock; PCODEBLOCK psSubCfgExitBlock; LayoutCfgFromCtrlDepNode(psState, psCtrlDepNode->u.sBlock.apsSucc[0], psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); { PCODEBLOCK psCndExeStBlock = AllocateBlock(psState, psCfg); PCODEBLOCK psCndExeEndBlock = AllocateBlock(psState, psCfg); PCODEBLOCK psCurrCodeBlock; AppendExecPredInst(psState, psCndExeStBlock, ICNDST, psCtrlDepNode->u.sBlock.psBlock->u.sCond.sPredSrc.uNumber, psCtrlDepNode->u.sBlock.auSuccIdx[0] == 0 ? IMG_FALSE : IMG_TRUE /* uCondPredInv */, USC_PREDREG_NONE, 1); psCurrCodeBlock = DuplicateCodeBlockIfNeeded(psState, bDuplicateCodeBlocks, psCtrlDepNode->u.sBlock.psBlock); SetBlockUnconditional(psState, psCurrCodeBlock, psCndExeStBlock); AppendExecPredInst(psState, psCndExeEndBlock, ICNDEND, USC_PREDREG_NONE, IMG_FALSE /* uCondPredInv */, USC_PREDREG_NONE, 1); SetBlockConditionalExecPred(psState, psCndExeStBlock, psSubCfgEntryBlock, psCndExeEndBlock, IMG_FALSE); SetBlockUnconditional(psState, psSubCfgExitBlock, psCndExeEndBlock); (*ppsEntryBlock) = psCurrCodeBlock; (*ppsExitBlock) = psCndExeEndBlock; } } else { PCODEBLOCK psSubCfgEntryBlock; PCODEBLOCK psSubCfgExitBlock; PCODEBLOCK psCndExeEfBlock; LayoutCfgFromCtrlDepNode(psState, psCtrlDepNode->u.sBlock.apsSucc[0], psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); psCndExeEfBlock = AllocateBlock(psState, psCfg); { PCODEBLOCK psCndExeStBlock = AllocateBlock(psState, psCfg); PCODEBLOCK psCurrCodeBlock; AppendExecPredInst(psState, psCndExeStBlock, ICNDST, psCtrlDepNode->u.sBlock.psBlock->u.sCond.sPredSrc.uNumber, psCtrlDepNode->u.sBlock.auSuccIdx[0] == 0 ? IMG_FALSE : IMG_TRUE /* uCondPredInv */, USC_PREDREG_NONE, 1); psCurrCodeBlock = DuplicateCodeBlockIfNeeded(psState, bDuplicateCodeBlocks, psCtrlDepNode->u.sBlock.psBlock); SetBlockUnconditional(psState, psCurrCodeBlock, psCndExeStBlock); AppendExecPredInst(psState, psCndExeEfBlock, ICNDEF, USC_PREDREG_NONE, IMG_TRUE /* uCondPredInv */, USC_PREDREG_NONE, 1); SetBlockConditionalExecPred(psState, psCndExeStBlock, psSubCfgEntryBlock, psCndExeEfBlock, IMG_FALSE); SetBlockUnconditional(psState, psSubCfgExitBlock, psCndExeEfBlock); (*ppsEntryBlock) = psCurrCodeBlock; } LayoutCfgFromCtrlDepNode(psState, psCtrlDepNode->u.sBlock.apsSucc[1], psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); { PCODEBLOCK psCndExeEndBlock = AllocateBlock(psState, psCfg); AppendExecPredInst(psState, psCndExeEndBlock, ICNDEND, USC_PREDREG_NONE, IMG_FALSE /* uCondPredInv */, USC_PREDREG_NONE, 1); SetBlockConditionalExecPred(psState, psCndExeEfBlock, psSubCfgEntryBlock, psCndExeEndBlock, IMG_FALSE); SetBlockUnconditional(psState, psSubCfgExitBlock, psCndExeEndBlock); (*ppsExitBlock) = psCndExeEndBlock; } } } else { PCODEBLOCK psPrevSubCfgExitBlock = NULL; PCODEBLOCK psSubCfgEntryBlock; PCODEBLOCK psSubCfgExitBlock; PUSC_LIST_ENTRY psListEntry; PCTRL_DEP_NODE_LISTENTRY psCtrlDepNodeLstEntry; for (psListEntry = psCtrlDepNode->u.sRegion.sSuccLst.psHead; psListEntry != NULL; psListEntry = psListEntry->psNext) { psCtrlDepNodeLstEntry = IMG_CONTAINING_RECORD(psListEntry, PCTRL_DEP_NODE_LISTENTRY, sListEntry); LayoutCfgFromCtrlDepNode(psState, psCtrlDepNodeLstEntry->psCtrlDepNode, psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); if (psPrevSubCfgExitBlock == NULL) { (*ppsEntryBlock) = psSubCfgEntryBlock; } else { SetBlockUnconditional(psState, psPrevSubCfgExitBlock, psSubCfgEntryBlock); } psPrevSubCfgExitBlock = psSubCfgExitBlock; } (*ppsExitBlock) = psPrevSubCfgExitBlock; } }