VirtualBox

Changeset 54446 in vbox


Ignore:
Timestamp:
Feb 24, 2015 1:02:31 PM (10 years ago)
Author:
vboxsync
Message:

RTMpOnPair implementation for linux.

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/linux/Makefile

    r54419 r54446  
    144144        generic/RTMpGetArraySize-generic.o \
    145145        generic/RTMpGetCoreCount-generic.o \
    146         generic/RTMpOnPair-generic.o \
    147146        generic/RTSemEventWait-2-ex-generic.o \
    148147        generic/RTSemEventWaitNoResume-2-ex-generic.o \
  • trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv

    r54419 r54446  
    156156    ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \
    157157    ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetCoreCount-generic.cpp=>generic/RTMpGetCoreCount-generic.c \
    158     ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpOnPair-generic.cpp=>generic/RTMpOnPair-generic.c \
    159158    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventWait-2-ex-generic.cpp=>generic/RTSemEventWait-2-ex-generic.c \
    160159    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventWaitNoResume-2-ex-generic.c \
  • trunk/src/VBox/Runtime/Makefile.kmk

    r54410 r54446  
    18701870        generic/RTMpGetCoreCount-generic.cpp \
    18711871        generic/mppresent-generic.cpp \
    1872         generic/RTMpOnPair-generic.cpp \
    18731872        r0drv/linux/alloc-r0drv-linux.c \
    18741873        r0drv/linux/assert-r0drv-linux.c \
  • trunk/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c

    r54415 r54446  
    214214
    215215/**
     216 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER, does hit
     217 * increment after calling the worker.
     218 *
     219 * @param   pvInfo      Pointer to the RTMPARGS package.
     220 */
     221static void rtmpLinuxWrapperPostInc(void *pvInfo)
     222{
     223    PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
     224    pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
     225    ASMAtomicIncU32(&pArgs->cHits);
     226}
     227
     228
     229/**
    216230 * Wrapper between the native linux all-cpu callbacks and PFNRTWORKER.
    217231 *
     
    318332
    319333
     334#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     335/**
     336 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
     337 * employed by RTMpOnPair on older kernels that lacks smp_call_function_many.
     338 *
     339 * @param   pvInfo      Pointer to the RTMPARGS package.
     340 */
     341static void rtMpLinuxOnPairWrapper(void *pvInfo)
     342{
     343    PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
     344    RTCPUID   idCpu = RTMpCpuId();
     345
     346    if (   idCpu == pArgs->idCpu
     347        || idCpu == pArgs->idCpu2)
     348    {
     349        pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
     350        ASMAtomicIncU32(&pArgs->cHits);
     351    }
     352}
     353#endif
     354
     355
     356RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
     357{
     358    int rc;
     359    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
     360
     361    AssertReturn(idCpu1 != idCpu2, VERR_INVALID_PARAMETER);
     362    AssertReturn(!(fFlags & RTMPON_F_VALID_MASK), VERR_INVALID_FLAGS);
     363
     364    /*
     365     * Check that both CPUs are online before doing the broadcast call.
     366     */
     367    RTThreadPreemptDisable(&PreemptState);
     368    if (   RTMpIsCpuOnline(idCpu1)
     369        && RTMpIsCpuOnline(idCpu2))
     370    {
     371        /*
     372         * Use the smp_call_function variant taking a cpu mask where available,
     373         * falling back on broadcast with filter.  Slight snag if one of the
     374         * CPUs is the one we're running on, we must do the call and the post
     375         * call wait ourselves.
     376         */
     377#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
     378        cpumask_t   DstCpuMask;
     379        RTCPUID     idCpuSelf = RTMpCpuId();
     380        bool const  fCallSelf = idCpuSelf == idCpu1 || idCpuSelf == idCpu2;
     381#endif
     382        RTMPARGS    Args;
     383        Args.pfnWorker = pfnWorker;
     384        Args.pvUser1 = pvUser1;
     385        Args.pvUser2 = pvUser2;
     386        Args.idCpu   = idCpu1;
     387        Args.idCpu2  = idCpu2;
     388        Args.cHits   = 0;
     389
     390#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
     391        cpumask_clear(&DstCpuMask);
     392        cpumask_set_cpu(idCpu1, &DstCpuMask);
     393        cpumask_set_cpu(idCpu2, &DstCpuMask);
     394#endif
     395
     396#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
     397        smp_call_function_many(&DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
     398        rc = 0;
     399#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
     400        rc = smp_call_function_many(&DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
     401#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
     402        rc = smp_call_function_mask(&DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
     403#else /* older kernels */
     404        rc = smp_call_function(rtMpLinuxOnPairWrapper, &Args, 0 /* retry */, 0 /* wait */);
     405#endif /* older kernels */
     406        Assert(rc == 0);
     407
     408
     409#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
     410        /* Call ourselves if necessary and wait for the other party to be done. */
     411        if (fCallSelf)
     412        {
     413            uint32_t cLoops = 0;
     414            rtmpLinuxWrapper(&Args);
     415            while (ASMAtomicReadU32(&Args.cHits) < 2)
     416            {
     417                if ((cLoops & 0x1ff) == 0 && !RTMpIsCpuOnline(idCpuSelf == idCpu1 ? idCpu2 : idCpu2))
     418                    break;
     419                cLoops++;
     420                ASMNopPause();
     421            }
     422        }
     423#endif
     424
     425        Assert(Args.cHits <= 2);
     426        if (Args.cHits == 2)
     427            rc = VINF_SUCCESS;
     428        else if (Args.cHits == 1)
     429            rc = VERR_NOT_ALL_CPUS_SHOWED;
     430        else if (Args.cHits == 0)
     431            rc = VERR_CPU_OFFLINE;
     432        else
     433            rc = VERR_CPU_IPE_1;
     434    }
     435    /*
     436     * A CPU must be present to be considered just offline.
     437     */
     438    else if (   RTMpIsCpuPresent(idCpu1)
     439             && RTMpIsCpuPresent(idCpu2))
     440        rc = VERR_CPU_OFFLINE;
     441    else
     442        rc = VERR_CPU_NOT_FOUND;
     443    RTThreadPreemptRestore(&PreemptState);;
     444    return rc;
     445}
     446RT_EXPORT_SYMBOL(RTMpOnPair);
     447
     448
     449RTDECL(bool) RTMpOnPairIsConcurrentExecSupported(void)
     450{
     451    return true;
     452}
     453RT_EXPORT_SYMBOL(RTMpOnPairIsConcurrentExecSupported);
    320454#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
    321455/**
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