Пример #1
0
DLL_EXPORT
void FishHang_LeaveCriticalSection
(
    const char*  pszFileReleasing,    // source file that attempted it
    const int    nLineReleasing,      // line number of source file

    LPCRITICAL_SECTION lpCriticalSection   // address of critical section object
)
{
    FISH_THREAD*  pFISH_THREAD;
    FISH_LOCK*    pFISH_LOCK;

    FIXFILENAME(pszFileReleasing);

    LockFishHang();

    if (!GetThreadAndLockPtrs(&pFISH_THREAD,&pFISH_LOCK,lpCriticalSection))
        FishHangAbort(pszFileReleasing,nLineReleasing);

    if (!bFishHangAtExit && pFISH_LOCK->pOwningThread != pFISH_THREAD)
    {
        logmsg(
            "\n** ERROR ** FISH_THREAD %8.8X "
            "releasing FISH_LOCK %8.8X "
            "owned by FISH_THREAD %8.8X!\n"
            "** Here's the culprit! --> %s(%d)\n",
            (int)pFISH_THREAD,
            (int)pFISH_LOCK,
            (int)pFISH_LOCK->pOwningThread,
            pszFileReleasing,nLineReleasing
            );

        RemoveListEntry(&pFISH_THREAD->ThreadListLink);
        InsertListHead(&ThreadsListHead,&pFISH_THREAD->ThreadListLink);
        PrintAllFISH_THREADs();

        if (pFISH_LOCK->pOwningThread)
        {
            RemoveListEntry(&pFISH_LOCK->ThreadLockListLink);
            InsertListHead(&pFISH_LOCK->pOwningThread->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink);
        }
        PrintAllFISH_LOCKs();
        FishHangAbort(pszFileReleasing,nLineReleasing);
    }
    else
    {
        pFISH_LOCK->nLockedDepth--;
    }

    if (pFISH_LOCK->nLockedDepth <= 0)
    {
        if (pFISH_LOCK->nLockedDepth < 0)
        {
            logmsg(
                "\n** ERROR ** FISH_THREAD %8.8X "
                "attempted to release FISH_LOCK %8.8X "
                "one too many times!?!\n"
                "** Here's the culprit! --> %s(%d)\n",
                (int)pFISH_THREAD,
                (int)pFISH_LOCK,
                pszFileReleasing,nLineReleasing
                );

            RemoveListEntry(&pFISH_THREAD->ThreadListLink);
            InsertListHead(&ThreadsListHead,&pFISH_THREAD->ThreadListLink);
            PrintAllFISH_THREADs();

            if (pFISH_LOCK->pOwningThread)
            {
                RemoveListEntry(&pFISH_LOCK->ThreadLockListLink);
                InsertListHead(&pFISH_LOCK->pOwningThread->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink);
            }
            PrintAllFISH_LOCKs();
            FishHangAbort(pszFileReleasing,nLineReleasing);
        }
        pFISH_LOCK->pOwningThread = NULL;
        RemoveListEntry(&pFISH_LOCK->ThreadLockListLink);
        InitializeListLink(&pFISH_LOCK->ThreadLockListLink);
    }

    UnlockFishHang();

    LeaveCriticalSection(lpCriticalSection);
}
Пример #2
0
int  ScheduleIORequest(void* pDevBlk, unsigned short wDevNum, int* pnDevPrio)
{
    /////////////////////////////////////////////////////////////////
    // PROGRAMMING NOTE: The various errors that can occur in this
    // function should probably be reported by returning cc1 with
    // 'channel control check' set (or something similar), but until
    // I can work out the details, I'm going to be lazy and just
    // return cc2 (subchannel busy) for now to allow the system to
    // retry the i/o request if it so desires. Hopefully the problem
    // was only intermittent and will work the second time around.
    /////////////////////////////////////////////////////////////////

    DEVIOREQUEST*    pIORequest;            // ptr to i/o request
    DEVTHREADPARMS*  pThreadParms;          // ptr to device_thread parameters

    // Create an i/o request queue entry for this i/o request

    pIORequest = (DEVIOREQUEST*) malloc(sizeof(DEVIOREQUEST));

    if (!pIORequest)
    {
        WRMSG ( HHC04111, "E", 0, wDevNum, "malloc(DEVIOREQUEST)", errno, strerror(errno) );
        return 2;
    }

    InitializeListLink(&pIORequest->IORequestListLinkingListEntry);
    pIORequest->pDevBlk = pDevBlk;
    pIORequest->wDevNum = wDevNum;
    pIORequest->pnDevPrio = pnDevPrio;

    // Schedule a device_thread to process this i/o request

    LockScheduler();        // (lock scheduler vars)

    if (ios_devtmax < 0)
    {
        // Create new "one time only" thread each time...

        // (Note: the device thread's parms will automatically
        //  be locked upon return if creation was successful.)

        RemoveDeadThreadsFromList();    // (prevent runaway list)

        if (!(pThreadParms = CreateDeviceThread(wDevNum)))
        {
            UnlockScheduler();          // (unlock scheduler vars)
            free(pIORequest);           // (discard i/o request)
            return 2;                   // (return device busy)
        }
    }
    else
    {
        // Select a non-busy device thread to handle this i/o request...

        // (Note: the device thread's parms will automatically
        //  be locked upon return if selection was successful.)

        if (!(pThreadParms = SelectDeviceThread()))
        {
            // All threads are currently busy or no threads exist yet.

            // Since the possibility of a deadlock[1] can easily occur if we schedule
            // an i/o request to a currently busy device thread[2], we have no choice
            // but to create another device thread.

            // [1] Not an actual programmatic deadlock of course, but nonetheless
            //     a deadlock from the guest operating system's point of view.

            // [2] A curently busy device thread could easily have its channel program
            //     suspended and thus would never see the queued request until such time
            //     its suspended channel program was resumed and allowed to complete, and
            //     if the request we queued (that would end up waiting to be processed
            //     by the currently suspended device thread) just so happens to be one
            //     that the operating system needs to have completed before it can resume
            //     the currently suspended channel program, then the operating system will
            //     obviously hang. (It would end up waiting for an i/o to complete that
            //     would never complete until the currently suspended channel program was
            //     resumed, which would never be resumed until the queued i/o completes,
            //     which would never even be processed until the currently suspended
            //     channel program is resumed ..... etc.)

            if (ios_devtmax && ios_devtnbr >= ios_devtmax)  // max threads already created?
            {
                WRMSG ( HHC04110, "W", ios_devtmax, ( ios_devtnbr - ios_devtmax ) + 1 );
                ios_devtunavail++;          // (count occurrences)
            }

            // Create a new device thread for this i/o request...

            // (Note: the device thread's parms will automatically
            //  be locked upon return if creation was successful.)

            if (!(pThreadParms = CreateDeviceThread(wDevNum)))
            {
                UnlockScheduler();          // (unlock scheduler vars)
                free(pIORequest);           // (discard i/o request)
                return 2;                   // (return device busy)
            }
        }
    }

    // (Note: the thread parms lock should still be held at this point)

    // Queue the i/o request to the selected device_thread's i/o request queue...

    InsertListTail(&pThreadParms->IORequestListHeadListEntry,&pIORequest->IORequestListLinkingListEntry);

    // Tell device_thread it has work (must do this while its request list is still
    // locked to prevent it from prematurely exiting in case it's just about to die)

    MySetEvent(pThreadParms->hRequestQueuedEvent);

    // Now unlock its request queue so it can process the request we just gave it

    UnlockThreadParms(pThreadParms);        // (let it proceed)

    // We're done, so unlock the scheduler vars so another cpu thread
    // in the configuration can schedule and i/o request and then exit
    // back the the startio function...

    UnlockScheduler();          // (unlock vars and exit; we're done)

    return 0;                   // (success)
}
Пример #3
0
DEVTHREADPARMS*  CreateDeviceThread(unsigned short wDevNum)
{
    DEVTHREADPARMS*  pThreadParms;      // ptr to returned device_thread parameters
    DWORD            dwThreadID;        // (work)

    pThreadParms = malloc(sizeof(DEVTHREADPARMS));      // (allocate structure)

    if (!pThreadParms)
    {
        logmsg(_("HHCCP086E malloc(DEVTHREADPARMS) failed; device=%4.4X, strerror=\"%s\"\n"),
            wDevNum,strerror(errno));
        return NULL;    // (error)
    }

    pThreadParms->hShutdownEvent = MyCreateEvent(NULL,TRUE,FALSE,NULL);

    if (!pThreadParms->hShutdownEvent)
    {
        logmsg(_("HHCCP087E CreateEvent(hShutdownEvent) failed; device=%4.4X, strerror=\"%s\"\n"),
            wDevNum,strerror(errno));
        free(pThreadParms);
        return NULL;    // (error)
    }

    pThreadParms->hRequestQueuedEvent = MyCreateEvent(NULL,TRUE,FALSE,NULL);

    if (!pThreadParms->hRequestQueuedEvent)
    {
        logmsg(_("HHCCP088E CreateEvent(hRequestQueuedEvent) failed; device=%4.4X, strerror=\"%s\"\n"),
            wDevNum,strerror(errno));
        MyCloseHandle(pThreadParms->hShutdownEvent);
        free(pThreadParms);
        return NULL;    // (error)
    }

    MyInitializeCriticalSection(&pThreadParms->IORequestListLock);

    InitializeListLink(&pThreadParms->ThreadListLinkingListEntry);
    InitializeListHead(&pThreadParms->IORequestListHeadListEntry);

    pThreadParms->bThreadIsDead = FALSE;
    pThreadParms->dwThreadID = 0;

    if (fthread_create(&dwThreadID,NULL,DeviceThread,pThreadParms,"DeviceThread") != 0)
    {
        logmsg(_("HHCCP089E fthread_create(DeviceThread) failed; device=%4.4X, strerror=\"%s\"\n"),
            wDevNum,strerror(errno));
        MyCloseHandle(pThreadParms->hShutdownEvent);
        MyCloseHandle(pThreadParms->hRequestQueuedEvent);
        MyDeleteCriticalSection(&pThreadParms->IORequestListLock);
        free(pThreadParms);
        return NULL;    // (error)
    }

    // Add the newly created device_thread to the end of our list of managed threads.

    InsertListTail(&ThreadListHeadListEntry,&pThreadParms->ThreadListLinkingListEntry);

    if (++ios_devtnbr > ios_devthwm) ios_devthwm = ios_devtnbr;

    LockThreadParms(pThreadParms);  // (lock thread parms before using)

    return pThreadParms;            // (success)
}