VirtualBox

Changeset 52581 in vbox


Ignore:
Timestamp:
Sep 3, 2014 12:19:42 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95853
Message:

Runtime/r0drv/linux: Reimplemented RTMpOnAll() to be used to execute code concurrently on all CPus.

Location:
trunk/src/VBox/Runtime/r0drv
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c

    r44529 r52581  
    187187
    188188/**
    189  * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
     189 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER.
    190190 *
    191191 * @param   pvInfo      Pointer to the RTMPARGS package.
     
    199199
    200200
     201/**
     202 * Wrapper between the native linux all-cpu callbacks and PFNRTWORKER.
     203 *
     204 * @param   pvInfo      Pointer to the RTMPARGS package.
     205 */
     206static void rtmpLinuxAllWrapper(void *pvInfo)
     207{
     208    PRTMPARGS  pArgs      = (PRTMPARGS)pvInfo;
     209    PRTCPUSET  pWorkerSet = pArgs->pWorkerSet;
     210    RTCPUID    idCpu      = RTMpCpuId();
     211    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     212
     213    if (RTCpuSetIsMember(pWorkerSet, idCpu))
     214    {
     215        pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
     216        RTCpuSetDel(pWorkerSet, idCpu);
     217    }
     218}
     219
     220
    201221RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
    202222{
    203223    int rc;
    204224    RTMPARGS Args;
    205 
    206 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
     225    RTCPUSET OnlineSet;
     226    RTCPUID  idCpu;
     227    uint32_t cLoops;
     228
    207229    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
    208 #endif
    209     Args.pfnWorker = pfnWorker;
    210     Args.pvUser1 = pvUser1;
    211     Args.pvUser2 = pvUser2;
    212     Args.idCpu = NIL_RTCPUID;
    213     Args.cHits = 0;
    214 
     230
     231    Args.pfnWorker  = pfnWorker;
     232    Args.pvUser1    = pvUser1;
     233    Args.pvUser2    = pvUser2;
     234    Args.idCpu      = NIL_RTCPUID;
     235    Args.cHits      = 0;
     236
     237    RTThreadPreemptDisable(&PreemptState);
     238    RTMpGetOnlineSet(&OnlineSet);
     239    Args.pWorkerSet = &OnlineSet;
     240    idCpu = RTMpCpuId();
     241
     242    if (RTCpuSetCount(&OnlineSet) > 1)
     243    {
     244        /* Fire the function on all other CPUs without waiting for completion. */
    215245#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
    216     rc = on_each_cpu(rtmpLinuxWrapper, &Args, 1 /* wait */);
    217 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    218     rc = on_each_cpu(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
    219 #else /* older kernels */
    220     RTThreadPreemptDisable(&PreemptState);
    221     rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
    222     local_irq_disable();
    223     rtmpLinuxWrapper(&Args);
    224     local_irq_enable();
     246        rc = smp_call_function(rtmpLinuxAllWrapper, &Args, 0 /* wait */);
     247#else
     248        rc = smp_call_function(rtmpLinuxAllWrapper, &Args, 0 /* retry */, 0 /* wait */);
     249#endif
     250        Assert(!rc); NOREF(rc);
     251    }
     252
     253    /* Fire the function on this CPU. */
     254    Args.pfnWorker(idCpu, Args.pvUser1, Args.pvUser2);
     255    RTCpuSetDel(Args.pWorkerSet, idCpu);
     256
     257    /* Wait for all of them finish. */
     258    cLoops = 64000;
     259    while (!RTCpuSetIsEmpty(Args.pWorkerSet))
     260    {
     261        /* Periodically check if any CPU in the wait set has gone offline, if so update the wait set. */
     262        if (!cLoops--)
     263        {
     264            RTCPUSET OnlineSetNow;
     265            RTMpGetOnlineSet(&OnlineSetNow);
     266            RTCpuSetAnd(Args.pWorkerSet, &OnlineSetNow);
     267
     268            cLoops = 64000;
     269        }
     270
     271        ASMNopPause();
     272    }
     273
    225274    RTThreadPreemptRestore(&PreemptState);
    226 #endif /* older kernels */
    227     Assert(rc == 0); NOREF(rc);
    228275    return VINF_SUCCESS;
    229276}
  • trunk/src/VBox/Runtime/r0drv/mp-r0drv.h

    r44529 r52581  
    5454    RTCPUID     idCpu;
    5555    uint32_t volatile cHits;
     56#ifdef RT_OS_LINUX
     57    PRTCPUSET   pWorkerSet;
     58#endif
    5659} RTMPARGS;
    5760/** Pointer to a RTMpOn* argument packet. */
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