VirtualBox

Ignore:
Timestamp:
Jun 17, 2021 9:40:24 AM (3 years ago)
Author:
vboxsync
Message:

VMM/DBGFR3SampleReport: Remove Windows specific changes and change the way how the sampling is started from the timer callback to avoid possible deadlocks between the timer callback and the EMTs doing the sampling

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFR3SampleReport.cpp

    r89722 r89763  
    135135    /** The report created after sampling was stopped. */
    136136    char                             *pszReport;
     137    /** Number of EMTs having a guest sample operation queued. */
     138    volatile uint32_t                cEmtsActive;
    137139    /** Array of per VCPU samples collected. */
    138140    DBGFSAMPLEREPORTVCPU             aCpus[1];
     
    377379 * each VCPU.
    378380 *
    379  * @returns Strict VBox status code.
    380  * @param   pVM                     The VM instance data.
    381  * @param   pVCpu                   The virtual CPU we execute on.
    382  * @param   pvUser                  Opaque user data.
    383  */
    384 static DECLCALLBACK(VBOXSTRICTRC) dbgfR3SampleReportSample(PVM pVM, PVMCPU pVCpu, void *pvUser)
    385 {
    386     RT_NOREF(pVM);
    387     PDBGFSAMPLEREPORTINT pThis = (PDBGFSAMPLEREPORTINT)pvUser;
     381 * @returns nothing.
     382 * @param   pThis                    Pointer to the sample report instance.
     383 */
     384static DECLCALLBACK(void) dbgfR3SampleReportSample(PDBGFSAMPLEREPORTINT pThis)
     385{
     386    PVM pVM = pThis->pUVM->pVM;
     387    PVMCPU pVCpu = VMMGetCpu(pVM);
    388388
    389389    PCDBGFSTACKFRAME pFrameFirst;
     
    437437        LogRelMax(10, ("Sampling guest stack on VCPU %u failed with rc=%Rrc\n", pVCpu->idCpu, rc));
    438438
    439     if (pVCpu->idCpu == 0)
    440     {
    441         /* Destroy the timer if requested. */
    442         if (ASMAtomicReadU32((volatile uint32_t *)&pThis->enmState) == DBGFSAMPLEREPORTSTATE_STOPPING)
    443         {
    444 #ifndef RT_OS_WINDOWS
    445             rc = RTTimerStop(pThis->hTimer); AssertRC(rc); RT_NOREF(rc);
    446 #endif
    447             rc = RTTimerDestroy(pThis->hTimer); AssertRC(rc); RT_NOREF(rc);
    448             pThis->hTimer = NULL;
    449 
    450             DBGFSAMPLEREPORTINFOHLP Hlp;
    451             PCDBGFINFOHLP           pHlp = &Hlp.Core;
    452 
    453             dbgfR3SampleReportInfoHlpInit(&Hlp);
    454 
    455             /* Some early dump code. */
    456             for (uint32_t i = 0; i < pThis->pUVM->cCpus; i++)
    457             {
    458                 PCDBGFSAMPLEREPORTVCPU pSampleVCpu = &pThis->aCpus[i];
    459 
    460                 pHlp->pfnPrintf(pHlp, "Sample report for vCPU %u:\n", i);
    461                 dbgfR3SampleReportDumpFrame(pHlp, pThis->pUVM, &pSampleVCpu->FrameRoot, 0);
    462             }
    463 
    464             /* Shameless copy from VMMGuruMeditation.cpp */
    465             static struct
    466             {
    467                 const char *pszInfo;
    468                 const char *pszArgs;
    469             } const     aInfo[] =
    470             {
    471                 { "mappings",        NULL },
    472                 { "mode",            "all" },
    473                 { "handlers",        "phys virt hyper stats" },
    474                 { "timers",          NULL },
    475                 { "activetimers",    NULL },
    476             };
    477             for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
    478             {
    479                 pHlp->pfnPrintf(pHlp,
    480                                 "!!\n"
    481                                 "!! {%s, %s}\n"
    482                                 "!!\n",
    483                                 aInfo[i].pszInfo, aInfo[i].pszArgs);
    484                 DBGFR3Info(pVM->pUVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
    485             }
    486 
    487             /* All other info items */
    488             DBGFR3InfoMulti(pVM,
    489                             "*",
    490                             "mappings|hma|cpum|cpumguest|cpumguesthwvirt|cpumguestinstr|cpumhyper|cpumhost|cpumvmxfeat|mode|cpuid"
    491                             "|pgmpd|pgmcr3|timers|activetimers|handlers|help|cfgm",
     439    /* Last EMT finishes the report when sampling was stopped. */
     440    uint32_t cEmtsActive = ASMAtomicDecU32(&pThis->cEmtsActive);
     441    if (   ASMAtomicReadU32((volatile uint32_t *)&pThis->enmState) == DBGFSAMPLEREPORTSTATE_STOPPING
     442        && !cEmtsActive)
     443    {
     444        rc = RTTimerDestroy(pThis->hTimer); AssertRC(rc); RT_NOREF(rc);
     445        pThis->hTimer = NULL;
     446
     447        DBGFSAMPLEREPORTINFOHLP Hlp;
     448        PCDBGFINFOHLP           pHlp = &Hlp.Core;
     449
     450        dbgfR3SampleReportInfoHlpInit(&Hlp);
     451
     452        /* Some early dump code. */
     453        for (uint32_t i = 0; i < pThis->pUVM->cCpus; i++)
     454        {
     455            PCDBGFSAMPLEREPORTVCPU pSampleVCpu = &pThis->aCpus[i];
     456
     457            pHlp->pfnPrintf(pHlp, "Sample report for vCPU %u:\n", i);
     458            dbgfR3SampleReportDumpFrame(pHlp, pThis->pUVM, &pSampleVCpu->FrameRoot, 0);
     459        }
     460
     461        /* Shameless copy from VMMGuruMeditation.cpp */
     462        static struct
     463        {
     464            const char *pszInfo;
     465            const char *pszArgs;
     466        } const     aInfo[] =
     467        {
     468            { "mappings",        NULL },
     469            { "mode",            "all" },
     470            { "handlers",        "phys virt hyper stats" },
     471            { "timers",          NULL },
     472            { "activetimers",    NULL },
     473        };
     474        for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
     475        {
     476            pHlp->pfnPrintf(pHlp,
    492477                            "!!\n"
    493                             "!! {%s}\n"
     478                            "!! {%s, %s}\n"
    494479                            "!!\n",
    495                             pHlp);
    496 
    497 
    498             /* done */
    499             pHlp->pfnPrintf(pHlp,
    500                             "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
    501 
    502             if (pThis->pszReport)
    503                 RTMemFree(pThis->pszReport);
    504             pThis->pszReport = Hlp.pachBuf;
    505             Hlp.pachBuf = NULL;
    506             dbgfR3SampleReportInfoHlpDelete(&Hlp);
    507 
    508             ASMAtomicXchgU32((volatile uint32_t *)&pThis->enmState, DBGFSAMPLEREPORTSTATE_READY);
    509 
    510             if (pThis->pfnProgress)
    511             {
    512                 pThis->pfnProgress(pThis->pvProgressUser, 100);
    513                 pThis->pfnProgress    = NULL;
    514                 pThis->pvProgressUser = NULL;
    515             }
    516 
    517             DBGFR3SampleReportRelease(pThis);
    518         }
    519     }
    520 
    521     return VINF_SUCCESS;
     480                            aInfo[i].pszInfo, aInfo[i].pszArgs);
     481            DBGFR3Info(pVM->pUVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
     482        }
     483
     484        /* All other info items */
     485        DBGFR3InfoMulti(pVM,
     486                        "*",
     487                        "mappings|hma|cpum|cpumguest|cpumguesthwvirt|cpumguestinstr|cpumhyper|cpumhost|cpumvmxfeat|mode|cpuid"
     488                        "|pgmpd|pgmcr3|timers|activetimers|handlers|help|cfgm",
     489                        "!!\n"
     490                        "!! {%s}\n"
     491                        "!!\n",
     492                        pHlp);
     493
     494
     495        /* done */
     496        pHlp->pfnPrintf(pHlp,
     497                        "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
     498
     499        if (pThis->pszReport)
     500            RTMemFree(pThis->pszReport);
     501        pThis->pszReport = Hlp.pachBuf;
     502        Hlp.pachBuf = NULL;
     503        dbgfR3SampleReportInfoHlpDelete(&Hlp);
     504
     505        ASMAtomicXchgU32((volatile uint32_t *)&pThis->enmState, DBGFSAMPLEREPORTSTATE_READY);
     506
     507        if (pThis->pfnProgress)
     508        {
     509            pThis->pfnProgress(pThis->pvProgressUser, 100);
     510            pThis->pfnProgress    = NULL;
     511            pThis->pvProgressUser = NULL;
     512        }
     513
     514        DBGFR3SampleReportRelease(pThis);
     515    }
    522516}
    523517
     
    528522static DECLCALLBACK(void) dbgfR3SampleReportTakeSample(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
    529523{
    530     RT_NOREF(pTimer);
    531524    PDBGFSAMPLEREPORTINT pThis = (PDBGFSAMPLEREPORTINT)pvUser;
    532525
     
    549542            ASMAtomicCmpXchgU32((volatile uint32_t *)&pThis->enmState, DBGFSAMPLEREPORTSTATE_STOPPING,
    550543                                DBGFSAMPLEREPORTSTATE_RUNNING);
    551         }
    552     }
    553 
    554     int rc = VMMR3EmtRendezvous(pThis->pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING,
    555                                 dbgfR3SampleReportSample, pThis);
    556     AssertRC(rc); RT_NOREF(rc);
     544
     545            rc = RTTimerStop(pTimer); AssertRC(rc); RT_NOREF(rc);
     546        }
     547    }
     548
     549    ASMAtomicAddU32(&pThis->cEmtsActive, pThis->pUVM->cCpus);
     550
     551    for (uint32_t i = 0; i < pThis->pUVM->cCpus; i++)
     552    {
     553        int rc = VMR3ReqCallVoidNoWait(pThis->pUVM->pVM, i, (PFNRT)dbgfR3SampleReportSample, 1, pThis);
     554        AssertRC(rc);
     555        if (RT_FAILURE(rc))
     556            ASMAtomicDecU32(&pThis->cEmtsActive);
     557    }
    557558}
    558559
     
    583584        pThis->cSampleIntervalUs = cSampleIntervalUs;
    584585        pThis->enmState          = DBGFSAMPLEREPORTSTATE_READY;
     586        pThis->cEmtsActive       = 0;
    585587
    586588        for (uint32_t i = 0; i < pUVM->cCpus; i++)
     
    684686    DBGFR3SampleReportRetain(pThis);
    685687
    686 #ifndef RT_OS_WINDOWS
    687688    rc = RTTimerCreateEx(&pThis->hTimer, pThis->cSampleIntervalUs * 1000,
    688689                         RTTIMER_FLAGS_CPU_ANY | RTTIMER_FLAGS_HIGH_RES,
     
    690691    if (RT_SUCCESS(rc))
    691692        rc = RTTimerStart(pThis->hTimer, 0 /*u64First*/);
    692 #else
    693     rc = RTTimerCreate(&pThis->hTimer, pThis->cSampleIntervalUs / 1000,
    694                        dbgfR3SampleReportTakeSample, pThis);
    695 #endif
    696 
    697693    if (RT_FAILURE(rc))
    698694    {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette