Пример #1
0
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;
}
Пример #2
0
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;
	}
}