RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { RTMPARGS Args; RT_ASSERT_INTS_ON(); if (idCpu >= ncpus) return VERR_CPU_NOT_FOUND; if (RT_UNLIKELY(!RTMpIsCpuOnline(idCpu))) return RTMpIsCpuPresent(idCpu) ? VERR_CPU_OFFLINE : VERR_CPU_NOT_FOUND; Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = idCpu; Args.cHits = 0; RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; RTThreadPreemptDisable(&PreemptState); RTSOLCPUSET CpuSet; for (int i = 0; i < IPRT_SOL_SET_WORDS; i++) CpuSet.auCpus[i] = 0; BT_SET(CpuSet.auCpus, idCpu); rtMpSolCrossCall(&CpuSet, rtMpSolOnSpecificCpuWrapper, &Args); RTThreadPreemptRestore(&PreemptState); Assert(ASMAtomicUoReadU32(&Args.cHits) <= 1); return ASMAtomicUoReadU32(&Args.cHits) == 1 ? VINF_SUCCESS : VERR_CPU_NOT_FOUND; }
RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { RTMPARGS Args; RT_ASSERT_INTS_ON(); Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = RTMpCpuId(); Args.cHits = 0; /* The caller is supposed to have disabled preemption, but take no chances. */ RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; RTThreadPreemptDisable(&PreemptState); RTSOLCPUSET CpuSet; for (int i = 0; i < IPRT_SOL_SET_WORDS; i++) CpuSet.auCpus[0] = (ulong_t)-1L; BT_CLEAR(CpuSet.auCpus, RTMpCpuId()); rtMpSolCrossCall(&CpuSet, rtMpSolOnOtherCpusWrapper, &Args); RTThreadPreemptRestore(&PreemptState); return VINF_SUCCESS; }
RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { int rc; RTMPARGS Args; RTSOLCPUSET CpuSet; RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; AssertReturn(idCpu1 != idCpu2, VERR_INVALID_PARAMETER); AssertReturn(!(fFlags & RTMPON_F_VALID_MASK), VERR_INVALID_FLAGS); Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = idCpu1; Args.idCpu2 = idCpu2; Args.cHits = 0; for (int i = 0; i < IPRT_SOL_SET_WORDS; i++) CpuSet.auCpus[i] = 0; BT_SET(CpuSet.auCpus, idCpu1); BT_SET(CpuSet.auCpus, idCpu2); /* * Check that both CPUs are online before doing the broadcast call. */ RTThreadPreemptDisable(&PreemptState); if ( RTMpIsCpuOnline(idCpu1) && RTMpIsCpuOnline(idCpu2)) { rtMpSolCrossCall(&CpuSet, rtMpSolOnPairCpuWrapper, &Args); Assert(Args.cHits <= 2); if (Args.cHits == 2) rc = VINF_SUCCESS; else if (Args.cHits == 1) rc = VERR_NOT_ALL_CPUS_SHOWED; else if (Args.cHits == 0) rc = VERR_CPU_OFFLINE; else rc = VERR_CPU_IPE_1; } /* * A CPU must be present to be considered just offline. */ else if ( RTMpIsCpuPresent(idCpu1) && RTMpIsCpuPresent(idCpu2)) rc = VERR_CPU_OFFLINE; else rc = VERR_CPU_NOT_FOUND; RTThreadPreemptRestore(&PreemptState); return rc; }
RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { RTMPARGS Args; RT_ASSERT_INTS_ON(); Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = NIL_RTCPUID; Args.cHits = 0; RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; RTThreadPreemptDisable(&PreemptState); RTSOLCPUSET CpuSet; for (int i = 0; i < IPRT_SOL_SET_WORDS; i++) CpuSet.auCpus[i] = (ulong_t)-1L; rtMpSolCrossCall(&CpuSet, rtMpSolOnAllCpuWrapper, &Args); RTThreadPreemptRestore(&PreemptState); return VINF_SUCCESS; }