Changeset 54402 in vbox for trunk/src/VBox/HostDrivers/Support
- Timestamp:
- Feb 23, 2015 8:50:46 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
r54395 r54402 142 142 static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 143 143 static void supdrvGipInitCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS, uint64_t uCpuHz); 144 static int supdrvMeasureInitialTscDeltas(PSUPDRVDEVEXT pDevExt);145 static int supdrvMeasureTscDeltaOne(PSUPDRVDEVEXT pDevExt, uint32_t idxWorker);146 144 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 147 145 static int supdrvTscDeltaThreadInit(PSUPDRVDEVEXT pDevExt); 148 146 static void supdrvTscDeltaTerm(PSUPDRVDEVEXT pDevExt); 149 147 static void supdrvTscDeltaThreadStartMeasurement(PSUPDRVDEVEXT pDevExt); 148 #else 149 static int supdrvMeasureInitialTscDeltas(PSUPDRVDEVEXT pDevExt); 150 static int supdrvMeasureTscDeltaOne(PSUPDRVDEVEXT pDevExt, uint32_t idxWorker); 150 151 #endif 151 152 … … 184 185 } 185 186 186 187 /**188 * Applies the TSC delta to the supplied raw TSC value.189 *190 * @returns VBox status code. (Ignored by all users, just FYI.)191 * @param pGip Pointer to the GIP.192 * @param puTsc Pointer to a valid TSC value before the TSC delta has been applied.193 * @param idApic The APIC ID of the CPU @c puTsc corresponds to.194 * @param fDeltaApplied Where to store whether the TSC delta was succesfully195 * applied or not (optional, can be NULL).196 *197 * @remarks Maybe called with interrupts disabled in ring-0!198 *199 * @note Don't you dare change the delta calculation. If you really do, make200 * sure you update all places where it's used (IPRT, SUPLibAll.cpp,201 * SUPDrv.c, supdrvGipMpEvent(), and more).202 */203 DECLINLINE(int) supdrvTscDeltaApply(PSUPGLOBALINFOPAGE pGip, uint64_t *puTsc, uint16_t idApic, bool *pfDeltaApplied)204 {205 int rc;206 207 /*208 * Validate input.209 */210 AssertPtr(puTsc);211 AssertPtr(pGip);212 Assert(pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED);213 214 /*215 * Carefully convert the idApic into a GIPCPU entry.216 */217 if (RT_LIKELY(idApic < RT_ELEMENTS(pGip->aiCpuFromApicId)))218 {219 uint16_t iCpu = pGip->aiCpuFromApicId[idApic];220 if (RT_LIKELY(iCpu < pGip->cCpus))221 {222 PSUPGIPCPU pGipCpu = &pGip->aCPUs[iCpu];223 224 /*225 * Apply the delta if valid.226 */227 if (RT_LIKELY(pGipCpu->i64TSCDelta != INT64_MAX))228 {229 *puTsc -= pGipCpu->i64TSCDelta;230 if (pfDeltaApplied)231 *pfDeltaApplied = true;232 return VINF_SUCCESS;233 }234 235 rc = VINF_SUCCESS;236 }237 else238 {239 AssertMsgFailed(("iCpu=%u cCpus=%u\n", iCpu, pGip->cCpus));240 rc = VERR_INVALID_CPU_INDEX;241 }242 }243 else244 {245 AssertMsgFailed(("idApic=%u\n", idApic));246 rc = VERR_INVALID_CPU_ID;247 }248 if (pfDeltaApplied)249 *pfDeltaApplied = false;250 return rc;251 }252 187 253 188 … … 771 706 772 707 /** 773 * Used by supdrvInitRefineInvariantTscFreqTimer() and 774 * supdrvGipInitMeasureTscFreq() to update the TSC frequency related GIP 775 * variables. 708 * Used by supdrvInitRefineInvariantTscFreqTimer and supdrvGipInitMeasureTscFreq 709 * to update the TSC frequency related GIP variables. 776 710 * 777 711 * @param pGip The GIP. … … 837 771 * an interrupt handler with higher priority than the clock 838 772 * interrupt, or spinning for ages in timer handlers is frowned 839 * upon, this codemust be disabled!773 * upon, this loop must be disabled! 840 774 * 841 775 * Darwin, FreeBSD, Linux, Solaris, Windows 8.1+: … … 1902 1836 if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC) 1903 1837 { 1904 rc = supdrvGipInitMeasureTscFreq(pDevExt, pGip, true /* fRough*/); /* cannot fail */1838 rc = supdrvGipInitMeasureTscFreq(pDevExt, pGip, true /*fRough*/); /* cannot fail */ 1905 1839 supdrvGipInitStartTimerForRefiningInvariantTscFreq(pDevExt, pGip); 1906 1840 } 1907 1841 else 1908 rc = supdrvGipInitMeasureTscFreq(pDevExt, pGip, false /* fRough*/);1842 rc = supdrvGipInitMeasureTscFreq(pDevExt, pGip, false /*fRough*/); 1909 1843 if (RT_SUCCESS(rc)) 1910 1844 { … … 2439 2373 { 2440 2374 /* 2441 * The calculations in supdrvGipUpdate() is very timing sensitive and doesn't handle 2442 * missed timer ticks. So for now it is better to use a delta of 0 and have the TSC rate 2443 * affected a bit until we get proper TSC deltas than implementing options like 2444 * rescheduling the tick to be delivered on the right CPU or missing the tick entirely. 2375 * The calculations in supdrvGipUpdate() is somewhat timing sensitive, 2376 * missing timer ticks is not an option for GIP because the GIP users 2377 * will end up incrementing the time in 1ns per time getter call until 2378 * there is a complete timer update. So, if the delta has yet to be 2379 * calculated, we just pretend it is zero for now (the GIP users 2380 * probably won't have it for a wee while either and will do the same). 2445 2381 * 2446 * The likely hood of this happening is really low. On Windows, Linux, and Solaris 2447 * timers fire on the CPU they were registered/started on. Darwin timers doesn't 2448 * necessarily (they are high priority threads waiting). 2382 * We could maybe on some platforms try cross calling a CPU with a 2383 * working delta here, but it's not worth the hassle since the 2384 * likelyhood of this happening is really low. On Windows, Linux, and 2385 * Solaris timers fire on the CPU they were registered/started on. 2386 * Darwin timers doesn't necessarily (they are high priority threads). 2449 2387 */ 2388 uint32_t iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId()); 2389 uint16_t iGipCpu = RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)) 2390 ? pGip->aiCpuFromCpuSetIdx[iCpuSet] : UINT16_MAX; 2450 2391 Assert(!ASMIntAreEnabled()); 2451 supdrvTscDeltaApply(pGip, &u64TSC, ASMGetApicId(), NULL /* pfDeltaApplied */); 2392 if (RT_LIKELY(iGipCpu < pGip->cCpus)) 2393 { 2394 int64_t iTscDelta = pGip->aCPUs[iGipCpu].i64TSCDelta; 2395 if (iTscDelta != INT64_MAX) 2396 u64TSC -= iTscDelta; 2397 } 2452 2398 } 2453 2399 … … 3167 3113 * The idea here is that we have the two CPUs execute the exact same code 3168 3114 * collecting a largish set of TSC samples. The code has one data dependency on 3169 * the other CPU w ith the intention to synchronize the execution as well3170 * ashelp cross references the two sets of TSC samples (the sequence numbers).3115 * the other CPU which intention it is to synchronize the execution as well as 3116 * help cross references the two sets of TSC samples (the sequence numbers). 3171 3117 * 3172 3118 * The @a fLag parameter is used to modify the execution a tiny bit on one or … … 3821 3767 */ 3822 3768 PSUPDRVGIPTSCDELTARGS pArgs = (PSUPDRVGIPTSCDELTARGS)RTMemAllocZ(sizeof(*pArgs)); 3823 if ( RT_LIKELY(pArgs))3769 if (pArgs) 3824 3770 { 3825 3771 pArgs->pWorker = pGipCpuWorker;
Note:
See TracChangeset
for help on using the changeset viewer.