VirtualBox

Changeset 90634 in vbox for trunk


Ignore:
Timestamp:
Aug 11, 2021 8:19:20 PM (3 years ago)
Author:
vboxsync
Message:

VMM/PDMCritSectRwEnterExcl: Implemented waiting in most ring-0 contexts. bugref:6695

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/vm.h

    r90597 r90634  
    13281328        struct PDM s;
    13291329#endif
    1330         uint8_t     padding[8256];      /* multiple of 64 */
     1330        uint8_t     padding[8320];      /* multiple of 64 */
    13311331    } pdm;
    13321332
     
    14631463
    14641464    /** Padding for aligning the structure size on a page boundrary. */
    1465     uint8_t         abAlignment2[1304 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
     1465    uint8_t         abAlignment2[1240 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
    14661466
    14671467    /* ---- end small stuff ---- */
  • trunk/include/VBox/vmm/vm.mac

    r90597 r90634  
    144144    .mm                     resb 192
    145145    alignb 64
    146     .pdm                    resb 8256
     146    .pdm                    resb 8320
    147147    alignb 64
    148148    .iom                    resb 1152
  • trunk/src/VBox/VMM/Makefile.kmk

    r89695 r90634  
    8181VBoxVMM_DEFS    += VMM_R0_SWITCH_STACK
    8282endif
    83 if "$(KBUILD_TYPE)" == "debug" && "$(USERNAME)" == "bird"
     83if "$(KBUILD_TYPE)" == "debug" && "$(USERNAME)" == "bird" && 0
    8484VBoxVMM_DEFS    += RTMEM_WRAP_TO_EF_APIS
    8585endif
  • trunk/src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp

    r90612 r90634  
    3939#if defined(IN_RING3) || defined(IN_RING0)
    4040# include <iprt/thread.h>
     41#endif
     42#ifdef IN_RING0
     43# include <iprt/time.h>
    4144#endif
    4245
     
    804807    RT_NOREF(hThreadSelf, rcBusy, pSrcPos, fNoVal, pVCpu);
    805808
     809    PSUPDRVSESSION const    pSession          = pVM->pSession;
     810    SUPSEMEVENT const       hEvent            = (SUPSEMEVENT)pThis->s.Core.hEvtWrite;
     811# ifdef IN_RING0
     812    uint64_t const          tsStart           = RTTimeNanoTS();
     813    uint64_t                cNsMaxTotal       = RT_NS_5MIN;
     814    uint64_t const          cNsMaxRetry       = RT_NS_15SEC;
     815    uint32_t                cMsMaxOne         = RT_MS_5SEC;
     816    bool                    fNonInterruptible = false;
     817# endif
     818
    806819    for (uint32_t iLoop = 0; ; iLoop++)
    807820    {
     
    815828                                                 RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_WRITE, false);
    816829        if (RT_SUCCESS(rc))
     830        { /* likely */ }
     831        else
     832            return pdmCritSectRwEnterExclBailOut(pThis, rc);
    817833#  else
    818834        RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, false);
    819835#  endif
    820836# endif
    821         {
    822             for (;;)
    823             {
    824                 rc = SUPSemEventWaitNoResume(pVM->pSession,
    825                                              (SUPSEMEVENT)pThis->s.Core.hEvtWrite,
    826                                              RT_INDEFINITE_WAIT);
    827                 if (   rc != VERR_INTERRUPTED
    828                     || pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    829                     break;
    830 # ifdef IN_RING0
    831                 pdmR0CritSectRwYieldToRing3(pVM);
     837        for (;;)
     838        {
     839            /*
     840             * We always wait with a timeout so we can re-check the structure sanity
     841             * and not get stuck waiting on a corrupt or deleted section.
     842             */
     843# ifdef IN_RING3
     844            rc = SUPSemEventWaitNoResume(pSession, hEvent, RT_MS_5SEC);
     845# else
     846            rc = !fNonInterruptible
     847               ? SUPSemEventWaitNoResume(pSession, hEvent, cMsMaxOne)
     848               : SUPSemEventWait(pSession, hEvent, cMsMaxOne);
     849            Log11Func(("%p: rc=%Rrc %'RU64 ns (cMsMaxOne=%RU64 hNativeWriter=%p)\n",
     850                       pThis, rc, RTTimeNanoTS() - tsStart, cMsMaxOne, pThis->s.Core.hNativeWriter));
    832851# endif
    833             }
    834 
    835 # ifdef IN_RING3
    836             RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
    837 # endif
    838             if (pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC)
     852            if (RT_LIKELY(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC))
    839853            { /* likely */ }
    840854            else
     855            {
     856# ifdef IN_RING3
     857                RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
     858# endif
    841859                return VERR_SEM_DESTROYED;
    842         }
    843         if (RT_FAILURE(rc))
    844             return pdmCritSectRwEnterExclBailOut(pThis, rc);
     860            }
     861            if (rc == VINF_SUCCESS)
     862            {
     863# ifdef IN_RING3
     864                RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
     865# endif
     866                break;
     867            }
     868
     869            /*
     870             * Timeout and interrupted waits needs careful handling in ring-0
     871             * because we're cooperating with ring-3 on this critical section
     872             * and thus need to make absolutely sure we won't get stuck here.
     873             *
     874             * The r0 interrupted case means something is pending (termination,
     875             * signal, APC, debugger, whatever), so we must try our best to
     876             * return to the caller and to ring-3 so it can be dealt with.
     877             */
     878            if (RT_LIKELY(rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED))
     879            {
     880# ifdef IN_RING0
     881                uint64_t const cNsElapsed = RTTimeNanoTS() - tsStart;
     882                int const      rcTerm     = RTThreadQueryTerminationStatus(NIL_RTTHREAD);
     883                AssertMsg(rcTerm == VINF_SUCCESS || rcTerm == VERR_NOT_SUPPORTED || rcTerm == VINF_THREAD_IS_TERMINATING,
     884                          ("rcTerm=%Rrc\n", rcTerm));
     885                if (rcTerm == VERR_NOT_SUPPORTED)
     886                    cNsMaxTotal = RT_NS_1MIN;
     887
     888                if (rc == VERR_TIMEOUT)
     889                {
     890                    /* Try return get out of here with a non-VINF_SUCCESS status if
     891                       the thread is terminating or if the timeout has been exceeded. */
     892                    STAM_REL_COUNTER_INC(&pVM->pdm.s.StatCritSectRwExclVerrTimeout);
     893                    if (   rcTerm == VINF_THREAD_IS_TERMINATING
     894                        || cNsElapsed > cNsMaxTotal)
     895                        return pdmCritSectRwEnterExclBailOut(pThis, rcBusy != VINF_SUCCESS ? rcBusy : rc);
     896                }
     897                else
     898                {
     899                    /* For interrupt cases, we must return if we can.  If rcBusy is VINF_SUCCESS,
     900                       we will try non-interruptible sleep for a while to help resolve the issue
     901                       w/o guru'ing. */
     902                    STAM_REL_COUNTER_INC(&pVM->pdm.s.StatCritSectRwExclVerrInterrupted);
     903                    if (   rcTerm != VINF_THREAD_IS_TERMINATING
     904                        && rcBusy == VINF_SUCCESS
     905                        && pVCpu != NULL
     906                        && cNsElapsed <= cNsMaxTotal)
     907                    {
     908                        if (!fNonInterruptible)
     909                        {
     910                            STAM_REL_COUNTER_INC(&pVM->pdm.s.StatCritSectRwExclNonInterruptibleWaits);
     911                            fNonInterruptible   = true;
     912                            cMsMaxOne           = 32;
     913                            uint64_t cNsLeft = cNsMaxTotal - cNsElapsed;
     914                            if (cNsLeft > RT_NS_10SEC)
     915                                cNsMaxTotal = cNsElapsed + RT_NS_10SEC;
     916                        }
     917                    }
     918                    else
     919                        return pdmCritSectRwEnterExclBailOut(pThis, rcBusy != VINF_SUCCESS ? rcBusy : rc);
     920
     921                }
     922# else  /* IN_RING3 */
     923                RT_NOREF(pVM, pVCpu, rcBusy);
     924# endif /* IN_RING3 */
     925            }
     926            /*
     927             * Any other return code is fatal.
     928             */
     929            else
     930            {
     931# ifdef IN_RING3
     932                RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
     933# endif
     934                AssertMsgFailed(("rc=%Rrc\n", rc));
     935                return RT_FAILURE_NP(rc) ? rc : -rc;
     936            }
     937        }
    845938
    846939        /*
     
    880973    AssertPtr(pThis);
    881974    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
    882 
    883 #if !defined(PDMCRITSECTRW_STRICT) || !defined(IN_RING3)
    884     NOREF(pSrcPos);
    885     NOREF(fNoVal);
    886 #endif
    887 #ifdef IN_RING3
    888     NOREF(rcBusy);
    889     NOREF(pVM);
    890 #endif
    891975
    892976    RTTHREAD hThreadSelf = NIL_RTTHREAD;
     
    10141098
    10151099    STAM_REL_COUNTER_INC(&pThis->s.CTX_MID_Z(StatContention,EnterExcl));
    1016 #if defined(IN_RING3) || defined(IN_RING0)
    1017 # ifdef IN_RING0
    1018     if (   RTThreadPreemptIsEnabled(NIL_RTTHREAD)
    1019         && ASMIntAreEnabled())
    1020 # endif
     1100
     1101    /*
     1102     * Ring-3 is pretty straight forward.
     1103     */
     1104#if defined(IN_RING3) && defined(PDMCRITSECTRW_STRICT)
     1105    return pdmR3R0CritSectRwEnterExclContended(pVM, NULL, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, hThreadSelf);
     1106#elif defined(IN_RING3)
     1107    return pdmR3R0CritSectRwEnterExclContended(pVM, NULL, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, RTThreadSelf());
     1108
     1109#elif defined(IN_RING0)
     1110    /*
     1111     * In ring-0 context we have to take the special VT-x/AMD-V HM context into
     1112     * account when waiting on contended locks.
     1113     */
     1114    PVMCPUCC pVCpu = VMMGetCpu(pVM);
     1115    if (pVCpu)
    10211116    {
    1022 # if defined(IN_RING3) && defined(PDMCRITSECTRW_STRICT)
    1023         if (hThreadSelf == NIL_RTTHREAD)
    1024             hThreadSelf = RTThreadSelfAutoAdopt();
    1025         return pdmR3R0CritSectRwEnterExclContended(pVM, NULL, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, hThreadSelf);
    1026 # elif defined(IN_RING3)
    1027         return pdmR3R0CritSectRwEnterExclContended(pVM, NULL, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, RTThreadSelf());
    1028 # else
    1029         return pdmR3R0CritSectRwEnterExclContended(pVM, NULL, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, NIL_RTTHREAD);
    1030 # endif
     1117        VMMR0EMTBLOCKCTX Ctx;
     1118        int rc = VMMR0EmtPrepareToBlock(pVCpu, rcBusy, __FUNCTION__, pThis, &Ctx);
     1119        if (rc == VINF_SUCCESS)
     1120        {
     1121            Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     1122
     1123            rc = pdmR3R0CritSectRwEnterExclContended(pVM, pVCpu, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, NIL_RTTHREAD);
     1124
     1125            VMMR0EmtResumeAfterBlocking(pVCpu, &Ctx);
     1126        }
     1127        else
     1128        {
     1129            //STAM_REL_COUNTER_INC(&pThis->s.StatContentionRZLockBusy);
     1130            rc = pdmCritSectRwEnterExclBailOut(pThis, rc);
     1131        }
     1132        return rc;
    10311133    }
    1032 #endif /* IN_RING3 || IN_RING0 */
    1033 
    1034 #ifndef IN_RING3
    1035     /* We cannot call SUPSemEventWaitNoResume in this context. Go back to
    1036        ring-3 and do it there or return rcBusy. */
     1134
     1135    /* Non-EMT. */
     1136    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     1137    return pdmR3R0CritSectRwEnterExclContended(pVM, NULL, pThis, hNativeSelf, pSrcPos, fNoVal, rcBusy, NIL_RTTHREAD);
     1138
     1139#else
     1140# error "Unused."
     1141    /*
     1142     * Raw-mode: Call host and take it there if rcBusy is VINF_SUCCESS.
     1143     */
    10371144    rcBusy = pdmCritSectRwEnterExclBailOut(pThis, rcBusy);
    10381145    if (rcBusy == VINF_SUCCESS)
  • trunk/src/VBox/VMM/VMMR3/PDMCritSect.cpp

    r90570 r90634  
    7272    STAM_REL_REG(pVM, &pVM->pdm.s.StatCritSectNonInterruptibleWaits, STAMTYPE_COUNTER, "/PDM/CritSects/00-Non-interruptible-Waits-VINF_SUCCESS",
    7373                 STAMUNIT_OCCURENCES, "Number of non-interruptible waits for rcBusy=VINF_SUCCESS");
     74
     75    STAM_REL_REG(pVM, &pVM->pdm.s.StatCritSectRwExclVerrInterrupted, STAMTYPE_COUNTER, "/PDM/CritSectsRw/00-Excl-VERR_INTERRUPTED", STAMUNIT_OCCURENCES,
     76                 "Number of VERR_INTERRUPTED returns in exclusive mode.");
     77    STAM_REL_REG(pVM, &pVM->pdm.s.StatCritSectRwExclVerrTimeout, STAMTYPE_COUNTER, "/PDM/CritSectsRw/00-Excl-VERR_TIMEOUT", STAMUNIT_OCCURENCES,
     78                 "Number of VERR_TIMEOUT returns in exclusive mode.");
     79    STAM_REL_REG(pVM, &pVM->pdm.s.StatCritSectRwExclNonInterruptibleWaits, STAMTYPE_COUNTER, "/PDM/CritSectsRw/00-Excl-Non-interruptible-Waits-VINF_SUCCESS",
     80                 STAMUNIT_OCCURENCES, "Number of non-interruptible waits for rcBusy=VINF_SUCCESS in exclusive mode");
    7481
    7582    /*
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r90570 r90634  
    14911491    STAMCOUNTER                     StatCritSectVerrInterrupted;
    14921492    STAMCOUNTER                     StatCritSectNonInterruptibleWaits;
     1493
     1494    STAMCOUNTER                     StatCritSectRwExclVerrTimeout;
     1495    STAMCOUNTER                     StatCritSectRwExclVerrInterrupted;
     1496    STAMCOUNTER                     StatCritSectRwExclNonInterruptibleWaits;
    14931497} PDM;
    14941498AssertCompileMemberAlignment(PDM, CritSect, 8);
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