RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet) { RTCPUID idCpu; RTCpuSetEmpty(pSet); idCpu = RTMpGetMaxCpuId(); do { if (RTMpIsCpuOnline(idCpu)) RTCpuSetAdd(pSet, idCpu); } while (idCpu-- > 0); return pSet; }
RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet) { RTCPUID idCpu; RTCpuSetEmpty(pSet); idCpu = RTMpGetMaxCpuId(); /* it's inclusive */ do { if (RTMpIsCpuPossible(idCpu)) RTCpuSetAdd(pSet, idCpu); } while (idCpu-- > 0); return pSet; }
RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet) { #ifdef CONFIG_SMP RTCPUID idCpu; RTCpuSetEmpty(pSet); idCpu = RTMpGetMaxCpuId(); do { if (RTMpIsCpuOnline(idCpu)) RTCpuSetAdd(pSet, idCpu); } while (idCpu-- > 0); #else RTCpuSetEmpty(pSet); RTCpuSetAdd(pSet, RTMpCpuId()); #endif return pSet; }
RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) { *ppTimer = NULL; /* * Validate flags. */ if (!RTTIMER_FLAGS_ARE_VALID(fFlags)) return VERR_INVALID_PARAMETER; if ( (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL && !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK))) return VERR_CPU_NOT_FOUND; /* * Allocate the timer handler. */ RTCPUID cSubTimers = 1; if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL) { cSubTimers = RTMpGetMaxCpuId() + 1; Assert(cSubTimers <= RTCPUSET_MAX_CPUS); /* On Windows we have a 1:1 relationship between cpuid and set index. */ } PRTTIMER pTimer = (PRTTIMER)RTMemAllocZ(RT_OFFSETOF(RTTIMER, aSubTimers[cSubTimers])); if (!pTimer) return VERR_NO_MEMORY; /* * Initialize it. */ pTimer->u32Magic = RTTIMER_MAGIC; pTimer->fSuspended = true; pTimer->fSpecificCpu = (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL; pTimer->fOmniTimer = (fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL; pTimer->idCpu = pTimer->fSpecificCpu ? RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK) : NIL_RTCPUID; pTimer->cSubTimers = cSubTimers; pTimer->pfnTimer = pfnTimer; pTimer->pvUser = pvUser; pTimer->u64NanoInterval = u64NanoInterval; KeInitializeTimerEx(&pTimer->NtTimer, SynchronizationTimer); if (pTimer->fOmniTimer) { /* * Initialize the per-cpu "sub-timers", select the first online cpu * to be the master. * ASSUMES that no cpus will ever go offline. */ pTimer->idCpu = NIL_RTCPUID; for (unsigned iCpu = 0; iCpu < cSubTimers; iCpu++) { pTimer->aSubTimers[iCpu].iTick = 0; pTimer->aSubTimers[iCpu].pParent = pTimer; if ( pTimer->idCpu == NIL_RTCPUID && RTMpIsCpuOnline(RTMpCpuIdFromSetIndex(iCpu))) { pTimer->idCpu = RTMpCpuIdFromSetIndex(iCpu); KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniMasterCallback, &pTimer->aSubTimers[iCpu]); } else KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniSlaveCallback, &pTimer->aSubTimers[iCpu]); KeSetImportanceDpc(&pTimer->aSubTimers[iCpu].NtDpc, HighImportance); KeSetTargetProcessorDpc(&pTimer->aSubTimers[iCpu].NtDpc, (int)RTMpCpuIdFromSetIndex(iCpu)); } Assert(pTimer->idCpu != NIL_RTCPUID); } else { /* * Initialize the first "sub-timer", target the DPC on a specific processor * if requested to do so. */ pTimer->aSubTimers[0].iTick = 0; pTimer->aSubTimers[0].pParent = pTimer; KeInitializeDpc(&pTimer->aSubTimers[0].NtDpc, rtTimerNtSimpleCallback, pTimer); KeSetImportanceDpc(&pTimer->aSubTimers[0].NtDpc, HighImportance); if (pTimer->fSpecificCpu) KeSetTargetProcessorDpc(&pTimer->aSubTimers[0].NtDpc, (int)pTimer->idCpu); } *ppTimer = pTimer; return VINF_SUCCESS; }