Quantcast
Channel: Common Language Runtime Internals and Architecture forum
Viewing all articles
Browse latest Browse all 1710

Please check is it a bug in clr

$
0
0

when i read the source code , i wonder, if the gc is trigger when one preemptive disable thread fall into the code (exactly method ofSpinUntil which is higlight as below),that will cause the app hang ,because all preemptive enabel threads is suspend, no handle is create or free.

------Handletablecache.cpp------------

void SyncTransferCacheHandles(OBJECTHANDLE *pDst, OBJECTHANDLE *pSrc, UINT uCount)
{
    WRAPPER_CONTRACT;

    /*
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    */
   
    // set up to loop
    // we loop backwards since that is the order handles are added to the bank
    // this is designed to reduce the chance that we will have to spin on a handle
    OBJECTHANDLE *pBase = pDst;
    pSrc += uCount;
    pDst += uCount;

    // loop until we've copied all of them
    while (pDst > pBase)
    {
        // advance to the next slot
        pDst--;
        pSrc--;

        // this version spins if there is no handle to read or no place to write it
        if (*pDst || !*pSrc)
        {
            SpinUntil(pSrc, TRUE);
            SpinUntil(pDst, FALSE);
        }

        // copy the handle and zero it from the source
        *pDst = *pSrc;
        *pSrc = 0;
    }
}

void SpinUntil(void *pCond, BOOL fNonZero)
{
    WRAPPER_CONTRACT;

    /*
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    */
   
    // if we have to sleep then we will keep track of a sleep period
    DWORD dwThisSleepPeriod = 1;    // first just give up our timeslice
    DWORD dwNextSleepPeriod = 10;   // next try a real delay

#ifdef _DEBUG
    DWORD dwTotalSlept = 0;
    DWORD dwNextComplain = 1000;
#endif //_DEBUG

    // on MP machines, allow ourselves some spin time before sleeping
    UINT uNonSleepSpins = 8 * (g_SystemInfo.dwNumberOfProcessors - 1);

    // spin until the specificed condition is met
    while ((*(UINT_PTR *)pCond != 0) != (fNonZero != 0))
    {
        // have we exhausted the non-sleep spin count?
        if (!uNonSleepSpins)
        {
#ifdef _DEBUG
            // yes, missed again - before sleeping, check our current sleep time
            if (dwTotalSlept >= dwNextComplain)
            {
                //
                // THIS SHOULD NOT NORMALLY HAPPEN
                //
                // The only time this assert can be ignored is if you have
                // another thread intentionally suspended in a way that either
                // directly or indirectly leaves a thread suspended in the
                // handle table while the current thread (this assert) is
                // running normally.
                //
                // Otherwise, this assert should be investigated as a bug.
                //
                _ASSERTE(FALSE);

                // slow down the assert rate so people can investigate
                dwNextComplain = 3 * dwNextComplain;
            }

            // now update our total sleep time
            dwTotalSlept += dwThisSleepPeriod;
#endif //_DEBUG

            // sleep for a little while
            __SwitchToThread(dwThisSleepPeriod);

            // now update our sleep period
            dwThisSleepPeriod = dwNextSleepPeriod;

            // now increase the next sleep period if it is still small
            if (dwNextSleepPeriod < 1000)
                dwNextSleepPeriod += 10;
        }
        else
        {
            // nope - just spin again
            YieldProcessor();           // indicate to the processor that we are spining
            uNonSleepSpins--;
        }
    }
}


Viewing all articles
Browse latest Browse all 1710

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>