Changeset 32572 in vbox
- Timestamp:
- Sep 16, 2010 4:18:12 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 65965
- Location:
- trunk
- Files:
-
- 1 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/mp.h
r28800 r32572 73 73 * Gets the max CPU identifier (inclusive). 74 74 * 75 * Inte ded for brute force enumerations, but use with75 * Intended for brute force enumerations, but use with 76 76 * care as it may be expensive. 77 77 * … … 80 80 RTDECL(RTCPUID) RTMpGetMaxCpuId(void); 81 81 82 /** 83 * Gets the size of a CPU array that is indexed by CPU set index. 84 * 85 * This takes both online, offline and hot-plugged cpus into account. 86 * 87 * @returns Number of elements. 88 * 89 * @remarks Use RTMpCpuIdToSetIndex to convert a RTCPUID into an array index. 90 */ 91 RTDECL(uint32_t) RTMpGetArraySize(void); 82 92 83 93 /** … … 102 112 * possibly be hotplugged later. 103 113 * 104 * @return The count. 114 * @returns The count. 115 * @remarks Don't use this for CPU array sizing, use RTMpGetArraySize instead. 105 116 */ 106 117 RTDECL(RTCPUID) RTMpGetCount(void); -
trunk/include/iprt/timer.h
r32504 r32572 93 93 * on every timer tick. 94 94 * @param pvUser User argument for the callback. 95 * @see RTTimerDestroy, RTTimerStop 95 * @see RTTimerCreateEx, RTTimerStart, RTTimerStop, RTTimerChangeInterval, 96 * RTTimerDestroy, RTTimerGetSystemGranularity 96 97 */ 97 98 RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser); … … 102 103 * @returns iprt status code. 103 104 * @retval VERR_NOT_SUPPORTED if an unsupported flag was specfied. 105 * @retval VERR_CPU_NOT_FOUND if the specified CPU 104 106 * 105 107 * @param ppTimer Where to store the timer handle. … … 111 113 * on every timer tick. 112 114 * @param pvUser User argument for the callback. 113 * @see RTTimerStart, RTTimerStop, RTTimerDestroy, RTTimerGetSystemGranularity 114 */ 115 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser); 115 * @see RTTimerStart, RTTimerStop, RTTimerChangeInterval, RTTimerDestroy, 116 * RTTimerGetSystemGranularity, RTTimerCanDoHighResolution 117 */ 118 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser); 116 119 117 120 /** @name RTTimerCreateEx flags 118 121 * @{ */ 119 122 /** Any CPU is fine. (Must be 0.) */ 120 #define RTTIMER_FLAGS_CPU_ANY 0123 #define RTTIMER_FLAGS_CPU_ANY UINT32_C(0) 121 124 /** One specific CPU */ 122 #define RTTIMER_FLAGS_CPU_SPECIFIC 125 #define RTTIMER_FLAGS_CPU_SPECIFIC RT_BIT(8) 123 126 /** Omni timer, run on all online CPUs. 124 127 * @remarks The timer callback isn't necessarily running at the time same time on each CPU. */ 125 #define RTTIMER_FLAGS_CPU_ALL 128 #define RTTIMER_FLAGS_CPU_ALL ( RTTIMER_FLAGS_CPU_MASK | RTTIMER_FLAGS_CPU_SPECIFIC ) 126 129 /** CPU mask. */ 127 #define RTTIMER_FLAGS_CPU_MASK 0xff 128 /** Convert a CPU number (0-based) to RTTimerCreateEx flags. 129 * This will automatically OR in the RTTIMER_FLAG_CPU_SPECIFIC flag. */ 130 #define RTTIMER_FLAGS_CPU(iCpu) ( (iCpu) | RTTIMER_FLAG_CPU_SPECIFIC ) 130 #define RTTIMER_FLAGS_CPU_MASK UINT32_C(0xff) 131 /** Desire a high resolution timer that works with RTTimerChangeInterval and 132 * isn't subject to RTTimerGetSystemGranularity rounding. 133 * @remarks This is quietly ignored if the feature isn't supported. */ 134 #define RTTIMER_FLAGS_HIGH_RES RT_BIT(9) 135 /** Convert a CPU set index (0-based) to RTTimerCreateEx flags. 136 * This will automatically OR in the RTTIMER_FLAGS_CPU_SPECIFIC flag. */ 137 #define RTTIMER_FLAGS_CPU(iCpu) ( (iCpu) | RTTIMER_FLAGS_CPU_SPECIFIC ) 131 138 /** Macro that validates the flags. */ 132 #define RTTIMER_FLAGS_ARE_VALID(fFlags) ( !((fFlags) & ~((fFlags) & RTTIMER_FLAGS_CPU_SPECIFIC ? 0x1ffU : 0x100U)) ) 139 #define RTTIMER_FLAGS_ARE_VALID(fFlags) \ 140 ( !((fFlags) & ~((fFlags) & RTTIMER_FLAGS_CPU_SPECIFIC ? UINT32_C(0x3ff) : UINT32_C(0x300))) ) 133 141 /** @} */ 134 142 … … 147 155 * @retval VERR_INVALID_HANDLE if pTimer isn't valid. 148 156 * @retval VERR_TIMER_ACTIVE if the timer isn't suspended. 157 * @retval VERR_CPU_OFFLINE if the CPU the timer was created to run on is not 158 * online (this include the case where it's not present in the 159 * system). 149 160 * 150 161 * @param pTimer The timer to activate. 151 162 * @param u64First The RTTimeSystemNanoTS() for when the timer should start 152 * firing (relative). If 0 is specified, the timer will fire ASAP. 163 * firing (relative). If 0 is specified, the timer will 164 * fire ASAP. 165 * @remarks When RTTimerCanDoHighResolution returns true, this API is 166 * callable with preemption disabled in ring-0. 153 167 * @see RTTimerStop 154 168 */ … … 161 175 * @retval VERR_INVALID_HANDLE if pTimer isn't valid. 162 176 * @retval VERR_TIMER_SUSPENDED if the timer isn't active. 163 * @retval VERR_NOT_SUPPORTED if the IPRT implementation doesn't support stopping a timer. 177 * @retval VERR_NOT_SUPPORTED if the IPRT implementation doesn't support 178 * stopping a timer. 164 179 * 165 180 * @param pTimer The timer to suspend. 181 * @remarks Can be called from the timer callback function to stop it. 166 182 * @see RTTimerStart 167 183 */ 168 184 RTDECL(int) RTTimerStop(PRTTIMER pTimer); 169 185 186 /** 187 * Changes the interval of a periodic timer. 188 * 189 * If the timer is active, it is implementation dependent whether the change 190 * takes place immediately or after the next tick. To get defined behavior, 191 * stop the timer before calling this API. 192 * 193 * @returns IPRT status code. 194 * @retval VERR_INVALID_HANDLE if pTimer isn't valid. 195 * @retval VERR_NOT_SUPPORTED if not supported. 196 * 197 * @param pTimer The timer to activate. 198 * @param u64NanoInterval The interval between timer ticks specified in 199 * nanoseconds. This is rounded to the fit the 200 * system timer granularity. 201 * @remarks Callable from the timer callback. Callable with preemption 202 * disabled in ring-0. 203 */ 204 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval); 170 205 171 206 /** … … 225 260 * 226 261 * @returns true if supported, false it not. 262 * 263 * @remarks Returning true also means RTTimerChangeInterval must be implemented 264 * and RTTimerStart be callable with preemption disabled. 227 265 */ 228 266 RTDECL(bool) RTTimerCanDoHighResolution(void); -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r32504 r32572 276 276 { "RTTimerStart", (void *)RTTimerStart }, 277 277 { "RTTimerStop", (void *)RTTimerStop }, 278 { "RTTimerChangeInterval", (void *)RTTimerChangeInterval }, 278 279 { "RTTimerGetSystemGranularity", (void *)RTTimerGetSystemGranularity }, 279 280 { "RTTimerRequestSystemGranularity", (void *)RTTimerRequestSystemGranularity }, … … 285 286 { "RTMpCpuIdFromSetIndex", (void *)RTMpCpuIdFromSetIndex }, 286 287 { "RTMpCpuIdToSetIndex", (void *)RTMpCpuIdToSetIndex }, 288 { "RTMpGetArraySize", (void *)RTMpGetArraySize }, 287 289 { "RTMpIsCpuPossible", (void *)RTMpIsCpuPossible }, 288 290 { "RTMpGetCount", (void *)RTMpGetCount }, … … 4904 4906 * ever increasing. We don't bother taking TSC rollover into account. 4905 4907 */ 4906 RTCPUSET CpuSet; 4907 int iLastCpu = RTCpuLastIndex(RTMpGetSet(&CpuSet)); 4908 int iEndCpu = RTMpGetArraySize(); 4908 4909 int iCpu; 4909 4910 int cLoops = 8; … … 4916 4917 while (cLoops-- > 0) 4917 4918 { 4918 for (iCpu = 0; iCpu < = iLastCpu; iCpu++)4919 for (iCpu = 0; iCpu < iEndCpu; iCpu++) 4919 4920 { 4920 4921 uint64_t CurTsc; … … 4952 4953 4953 4954 /* broke out of the loop. */ 4954 if (iCpu < = iLastCpu)4955 if (iCpu < iEndCpu) 4955 4956 break; 4956 4957 } 4957 4958 4958 4959 *poffMin = offMin; /* Almost RTMpOnSpecific profiling. */ 4959 Log(("supdrvDetermineAsyncTsc: returns %d; i LastCpu=%d rc=%d offMin=%llx offMax=%llx\n",4960 fAsync, i LastCpu, rc, offMin, offMax));4960 Log(("supdrvDetermineAsyncTsc: returns %d; iEndCpu=%d rc=%d offMin=%llx offMax=%llx\n", 4961 fAsync, iEndCpu, rc, offMin, offMax)); 4961 4962 #if !defined(RT_OS_SOLARIS) && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) 4962 4963 OSDBGPRINT(("vboxdrv: fAsync=%d offMin=%#lx offMax=%#lx\n", fAsync, (long)offMin, (long)offMax)); -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r32504 r32572 193 193 * - Nothing. 194 194 */ 195 #define SUPDRV_IOC_VERSION 0x0015000 2195 #define SUPDRV_IOC_VERSION 0x00150003 196 196 197 197 /** SUP_IOCTL_COOKIE. */ -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r32504 r32572 269 269 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION; 270 270 const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00150000 271 ? 0x0015000 2271 ? 0x00150003 272 272 : SUPDRV_IOC_VERSION & 0xffff0000; 273 273 CookieReq.u.In.u32MinVersion = uMinVersion; … … 424 424 { "RTR0MemObjMapKernel", 0xefef001b }, 425 425 { "RTR0MemObjMapKernelEx", 0xefef001c }, 426 { "RTMpGetArraySize", 0xefef001c }, 426 427 { "RTProcSelf", 0xefef001d }, 427 428 { "RTR0ProcHandleSelf", 0xefef001e }, … … 459 460 { "RTTimerStart", 0xefef003a }, 460 461 { "RTTimerStop", 0xefef003a }, 462 { "RTTimerChangeInterval", 0xefef003a }, 461 463 { "RTTimerGetSystemGranularity", 0xefef003a }, 462 464 { "RTTimerRequestSystemGranularity", 0xefef003a }, -
trunk/src/VBox/HostDrivers/Support/SUPR0.def
r32507 r32572 138 138 RTTimerStart 139 139 RTTimerStop 140 RTTimerChangeInterval 140 141 RTTimerGetSystemGranularity 141 142 RTTimerRequestSystemGranularity … … 143 144 RTTimerCanDoHighResolution 144 145 146 RTMpCpuId 147 RTMpCpuIdToSetIndex 148 RTMpGetArraySize 149 RTMpGetCount 150 RTMpIsCpuOnline 151 RTMpIsCpuWorkPending 145 152 RTMpOnAll 146 153 RTMpOnOthers 147 154 RTMpOnSpecific 148 155 RTMpPokeCpu 149 RTMpIsCpuOnline150 RTMpGetCount151 RTMpCpuIdToSetIndex152 RTMpCpuId153 RTMpIsCpuWorkPending154 156 RTPowerNotificationRegister 155 157 RTPowerNotificationDeregister -
trunk/src/VBox/HostDrivers/Support/freebsd/Makefile
r31842 r32572 125 125 RTLogWriteStdErr-stub-generic.c \ 126 126 RTLogWriteUser-generic.c \ 127 RTMpGetArraySize-generic.c \ 127 128 RTRandAdvCreateSystemFaster-generic.c \ 128 129 RTRandAdvCreateSystemTruer-generic.c \ -
trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv
r31847 r32572 150 150 ${PATH_ROOT}/src/VBox/Runtime/generic/uuid-generic.cpp=>generic/uuid-generic.c \ 151 151 ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \ 152 ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \ 152 153 ${PATH_ROOT}/src/VBox/Runtime/generic/timer-generic.cpp=>generic/timer-generic.c \ 153 154 ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \ -
trunk/src/VBox/HostDrivers/Support/linux/Makefile
r32537 r32572 130 130 generic/RTLogWriteStdOut-stub-generic.o \ 131 131 generic/RTLogWriteUser-generic.o \ 132 generic/RTMpGetArraySize-generic.o \ 132 133 generic/RTTimerCreate-generic.o \ 133 134 generic/uuid-generic.o \ -
trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
r32504 r32572 128 128 ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteStdOut-stub-generic.cpp=>generic/RTLogWriteStdOut-stub-generic.c \ 129 129 ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteUser-generic.cpp=>generic/RTLogWriteUser-generic.c \ 130 ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \ 130 131 ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \ 131 132 ${PATH_ROOT}/src/VBox/Runtime/generic/uuid-generic.cpp=>generic/uuid-generic.c \ -
trunk/src/VBox/Runtime/Makefile.kmk
r32529 r32572 1390 1390 generic/RTLogWriteStdErr-stub-generic.cpp \ 1391 1391 generic/RTLogWriteUser-generic.cpp \ 1392 generic/RTMpGetArraySize-generic.cpp \ 1392 1393 generic/RTRandAdvCreateSystemFaster-generic.cpp \ 1393 1394 generic/uuid-generic.cpp \ -
trunk/src/VBox/Runtime/generic/timer-generic.cpp
r32504 r32572 87 87 88 88 89 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)89 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 90 90 { 91 91 *ppTimer = NULL; … … 225 225 } 226 226 RT_EXPORT_SYMBOL(RTTimerStop); 227 228 229 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 230 { 231 if (!rtTimerIsValid(pTimer)) 232 return VERR_INVALID_HANDLE; 233 return VERR_NOT_SUPPORTED; 234 } 235 RT_EXPORT_SYMBOL(RTTimerChangeInterval); 227 236 228 237 -
trunk/src/VBox/Runtime/r0drv/freebsd/timer-r0drv-freebsd.c
r32504 r32572 90 90 91 91 92 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)92 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 93 93 { 94 94 *ppTimer = NULL; … … 102 102 && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL 103 103 && (fFlags & RTTIMER_FLAGS_CPU_MASK) > mp_maxid) 104 return VERR_ INVALID_PARAMETER;104 return VERR_CPU_NOT_FOUND; 105 105 106 106 /* … … 166 166 if (!pTimer->fSuspended) 167 167 return VERR_TIMER_ACTIVE; 168 if ( pTimer->fSpecificCpu 169 && !RTMpIsCpuOnline(pTimer->idCpu)) 170 return VERR_CPU_OFFLINE; 168 171 169 172 /* … … 199 202 200 203 return VINF_SUCCESS; 204 } 205 206 207 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 208 { 209 if (!rtTimerIsValid(pTimer)) 210 return VERR_INVALID_HANDLE; 211 return VERR_NOT_SUPPORTED; 201 212 } 202 213 -
trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c
r32504 r32572 5 5 6 6 /* 7 * Copyright (C) 2006-20 08Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 44 44 #include "internal/magics.h" 45 45 46 /* We use the API of Linux 2.6.28+ (hrtimer_add_expires_ns()) */ 47 #if !defined(RT_USE_LINUX_HRTIMER) \ 48 && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) \ 46 /** @def RTTIMER_LINUX_HAVE_HRTIMER 47 * Whether the kernel support high resolution timers (Linux kernel versions 48 * 2.6.28 and later (hrtimer_add_expires_ns()). */ 49 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 50 # define RTTIMER_LINUX_HAVE_HRTIMER 51 #endif 52 53 /** @def RTTIMER_LINUX_ONLY_HRTIMER 54 * Whether to use high resolution timers for everything or not. Implies 55 * RTTIMER_LINUX_WITH_HRTIMER. */ 56 #if !defined(RTTIMER_LINUX_ONLY_HRTIMER) \ 57 && defined(RTTIMER_LINUX_HAVE_HRTIMER) \ 49 58 && 0 /* currently disabled */ 50 # define RT _USE_LINUX_HRTIMER59 # define RTTIMER_LINUX_ONLY_HRTIMER 51 60 #endif 52 61 53 62 /* This check must match the ktime usage in rtTimeGetSystemNanoTS() / time-r0drv-linux.c. */ 54 #if defined(RT_USE_LINUX_HRTIMER) \ 55 && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) 56 # error "RT_USE_LINUX_HRTIMER requires 2.6.28 or later, sorry." 63 #if defined(RTTIMER_LINUX_ONLY_HRTIMER) \ 64 && !defined(RTTIMER_LINUX_HAVE_HRTIMER) 65 # error "RTTIMER_LINUX_ONLY_HRTIMER requires 2.6.28 or later, sorry." 66 #endif 67 68 /** @def RTTIMER_LINUX_WITH_HRTIMER 69 * Whether to use high resolution timers. */ 70 #if !defined(RTTIMER_LINUX_WITH_HRTIMER) \ 71 && defined(RTTIMER_LINUX_HAVE_HRTIMER) 72 # define RTTIMER_LINUX_WITH_HRTIMER 57 73 #endif 58 74 … … 96 112 typedef struct RTTIMERLNXSUBTIMER 97 113 { 98 /** The linux timer structure. */ 99 #ifdef RT_USE_LINUX_HRTIMER 100 struct hrtimer LnxTimer; 101 #else 102 struct timer_list LnxTimer; 103 /** The start of the current run (ns). 104 * This is used to calculate when the timer ought to fire the next time. */ 105 uint64_t u64StartTS; 106 /** The start of the current run (ns). 107 * This is used to calculate when the timer ought to fire the next time. */ 108 uint64_t u64NextTS; 109 #endif 110 /** The current tick number (since u64StartTS). */ 114 /** Timer specific data. */ 115 union 116 { 117 #if defined(RTTIMER_LINUX_WITH_HRTIMER) 118 /** High resolution timer. */ 119 struct 120 { 121 /** The linux timer structure. */ 122 struct hrtimer LnxTimer; 123 } Hr; 124 #endif 125 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 126 /** Standard timer. */ 127 struct 128 { 129 /** The linux timer structure. */ 130 struct timer_list LnxTimer; 131 /** The start of the current run (ns). 132 * This is used to calculate when the timer ought to fire the next time. */ 133 uint64_t u64StartTS; 134 /** The start of the current run (ns). 135 * This is used to calculate when the timer ought to fire the next time. */ 136 uint64_t u64NextTS; 137 /** The u64NextTS in jiffies. */ 138 unsigned long ulNextJiffies; 139 } Std; 140 #endif 141 } u; 142 /** The current tick number (since u.Std.u64StartTS). */ 111 143 uint64_t iTick; 112 144 /** Pointer to the parent timer. */ 113 145 PRTTIMER pParent; 114 #ifndef RT_USE_LINUX_HRTIMER115 /** The u64NextTS in jiffies. */116 unsigned long ulNextJiffies;117 #endif118 146 /** The current sub-timer state. */ 119 147 RTTIMERLNXSTATE volatile enmState; … … 121 149 /** Pointer to a linux sub-timer. */ 122 150 typedef RTTIMERLNXSUBTIMER *PRTTIMERLNXSUBTIMER; 123 AssertCompileMemberOffset(RTTIMERLNXSUBTIMER, LnxTimer, 0);124 151 125 152 … … 144 171 bool fAllCpus; 145 172 #endif /* else: All -> specific on non-SMP kernels */ 146 /** The CPU it must run on if fSpecificCpu is set. */ 173 /** Whether it is a high resolution timer or a standard one. */ 174 bool fHighRes; 175 /** The id of the CPU it must run on if fSpecificCpu is set. */ 147 176 RTCPUID idCpu; 148 177 /** The number of CPUs this timer should run on. */ … … 153 182 void *pvUser; 154 183 /** The timer interval. 0 if one-shot. */ 155 uint64_t 156 #ifndef RT _USE_LINUX_HRTIMER184 uint64_t volatile u64NanoInterval; 185 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 157 186 /** This is set to the number of jiffies between ticks if the interval is 158 187 * an exact number of jiffies. */ … … 210 239 } 211 240 212 213 #ifdef RT_USE_LINUX_HRTIMER 241 #ifdef RTTIMER_LINUX_WITH_HRTIMER 242 214 243 /** 215 244 * Converts a nano second time stamp to ktime_t. … … 239 268 } 240 269 241 #else /* ! RT_USE_LINUX_HRTIMER */ 242 270 #endif /* RTTIMER_LINUX_WITH_HRTIMER */ 271 272 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 243 273 /** 244 274 * Converts a nano second interval to jiffies. … … 258 288 return (cNanoSecs + (TICK_NSEC-1)) / TICK_NSEC; 259 289 } 260 #endif /* ! RT_USE_LINUX_HRTIMER */290 #endif /* !RTTIMER_LINUX_ONLY_HRTIMER */ 261 291 262 292 … … 269 299 * @param fPinned true = timer pinned to a specific CPU, 270 300 * false = timer can migrate between CPUs 271 */ 272 static void rtTimerLnxStartSubTimer(PRTTIMERLNXSUBTIMER pSubTimer, uint64_t u64Now, uint64_t u64First, bool fPinned) 301 * @param fHighRes Whether the user requested a high resolution timer or not. 302 */ 303 static void rtTimerLnxStartSubTimer(PRTTIMERLNXSUBTIMER pSubTimer, uint64_t u64Now, uint64_t u64First, 304 bool fPinned, bool fHighRes) 273 305 { 274 306 /* … … 276 308 */ 277 309 uint64_t u64NextTS = u64Now + u64First; 278 #ifndef RT_USE_LINUX_HRTIMER 279 pSubTimer->u64StartTS = u64NextTS; 280 pSubTimer->u64NextTS = u64NextTS; 310 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 311 if (fHighRes) 312 { 313 pSubTimer->u.Std.u64StartTS = u64NextTS; 314 pSubTimer->u.Std.u64NextTS = u64NextTS; 315 } 281 316 #endif 282 317 283 318 pSubTimer->iTick = 0; 284 319 285 #ifdef RT_USE_LINUX_HRTIMER 286 hrtimer_start(&pSubTimer->LnxTimer, rtTimerLnxNanoToKt(u64NextTS), 287 fPinned ? HRTIMER_MODE_ABS_PINNED : HRTIMER_MODE_ABS); 288 #else 320 #ifdef RTTIMER_LINUX_WITH_HRTIMER 321 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 322 if (fHighRes) 323 # endif 324 hrtimer_start(&pSubTimer->u.Hr.LnxTimer, rtTimerLnxNanoToKt(u64NextTS), 325 fPinned ? HRTIMER_MODE_ABS_PINNED : HRTIMER_MODE_ABS); 326 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 327 else 328 # endif 329 #endif 330 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 289 331 { 290 332 unsigned long cJiffies = !u64First ? 0 : rtTimerLnxNanoToJiffies(u64First); 291 pSubTimer->u lNextJiffies = jiffies + cJiffies;333 pSubTimer->u.Std.ulNextJiffies = jiffies + cJiffies; 292 334 # ifdef CONFIG_SMP 293 335 if (fPinned) 294 mod_timer_pinned(&pSubTimer-> LnxTimer, pSubTimer->ulNextJiffies);336 mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies); 295 337 else 296 338 # endif 297 mod_timer(&pSubTimer-> LnxTimer, pSubTimer->ulNextJiffies);339 mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies); 298 340 } 299 341 #endif … … 310 352 static void rtTimerLnxStopSubTimer(PRTTIMERLNXSUBTIMER pSubTimer) 311 353 { 312 #ifdef RT_USE_LINUX_HRTIMER 313 hrtimer_cancel(&pSubTimer->LnxTimer); 314 #else 315 if (timer_pending(&pSubTimer->LnxTimer)) 316 del_timer_sync(&pSubTimer->LnxTimer); 354 #ifdef RTTIMER_LINUX_WITH_HRTIMER 355 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 356 if (pSubTimer->pParent->fHighRes) 357 # endif 358 hrtimer_cancel(&pSubTimer->u.Hr.LnxTimer); 359 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 360 else 361 # endif 362 #endif 363 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 364 { 365 if (timer_pending(&pSubTimer->u.Std.LnxTimer)) 366 del_timer_sync(&pSubTimer->u.Std.LnxTimer); 367 } 317 368 #endif 318 369 … … 321 372 322 373 323 #ifdef RT_USE_LINUX_HRTIMER 324 /** 325 * Timer callback function. 326 * @returns HRTIMER_NORESTART or HRTIMER_RESTART depending on whether it's a one-shot or interval timer. 374 #ifdef RTTIMER_LINUX_WITH_HRTIMER 375 /** 376 * Timer callback function for high resolution timers. 377 * 378 * @returns HRTIMER_NORESTART or HRTIMER_RESTART depending on whether it's a 379 * one-shot or interval timer. 327 380 * @param pHrTimer Pointer to the sub-timer structure. 328 381 */ 329 static enum hrtimer_restart rtTimerLinuxCallback(struct hrtimer *pHrTimer) 330 #else 331 /** 332 * Timer callback function. 333 * @param ulUser Address of the sub-timer structure. 334 */ 335 static void rtTimerLinuxCallback(unsigned long ulUser) 336 #endif 337 { 338 #ifdef RT_USE_LINUX_HRTIMER 339 enum hrtimer_restart rc; 340 PRTTIMERLNXSUBTIMER pSubTimer = (PRTTIMERLNXSUBTIMER)pHrTimer; 341 #else 342 PRTTIMERLNXSUBTIMER pSubTimer = (PRTTIMERLNXSUBTIMER)ulUser; 343 #endif 344 PRTTIMER pTimer = pSubTimer->pParent; 382 static enum hrtimer_restart rtTimerLinuxHrCallback(struct hrtimer *pHrTimer) 383 { 384 PRTTIMERLNXSUBTIMER pSubTimer = RT_FROM_MEMBER(pHrTimer, RTTIMERLNXSUBTIMER, u.Hr.LnxTimer); 385 PRTTIMER pTimer = pSubTimer->pParent; 386 enum hrtimer_restart rc; 345 387 346 388 /* … … 359 401 { 360 402 rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_ACTIVE); 361 # ifdef RT_USE_LINUX_HRTIMER362 403 rc = HRTIMER_NORESTART; 363 # endif364 404 } 365 405 else if (!pTimer->u64NanoInterval) … … 371 411 ASMAtomicWriteBool(&pTimer->fSuspended, true); 372 412 rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_ACTIVE); 373 #ifdef RT_USE_LINUX_HRTIMER374 413 rc = HRTIMER_NORESTART; 375 #else376 /* detached before we're called, nothing to do for this case. */377 #endif378 379 414 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick); 380 415 } 381 416 else 382 417 { 418 /* 419 * Run the timer. Update the timer after calling the method. 420 */ 383 421 const uint64_t iTick = ++pSubTimer->iTick; 384 385 #ifdef RT_USE_LINUX_HRTIMER 386 hrtimer_add_expires_ns(&pSubTimer->LnxTimer, pTimer->u64NanoInterval); 387 rc = HRTIMER_RESTART; 388 #else 389 const uint64_t u64NanoTS = RTTimeNanoTS(); 390 422 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 423 424 /** @todo Check reference counting wrt. RTTimerDestroy from the 425 * callback? */ 426 if ( pSubTimer->enmState == RTTIMERLNXSTATE_ACTIVE 427 || pSubTimer->enmState == RTTIMERLNXSTATE_MP_STARTING) 428 { 429 hrtimer_add_expires_ns(&pSubTimer->u.Hr.LnxTimer, ASMAtomicReadU64(&pTimer->u64NanoInterval)); 430 rc = HRTIMER_RESTART; 431 } 432 else 433 rc = HRTIMER_NORESTART; 434 } 435 436 return rc; 437 } 438 #endif /* RTTIMER_LINUX_ONLY_HRTIMER */ 439 440 441 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 442 /** 443 * Timer callback function for standard timers. 444 * 445 * @param ulUser Address of the sub-timer structure. 446 */ 447 static void rtTimerLinuxStdCallback(unsigned long ulUser) 448 { 449 PRTTIMERLNXSUBTIMER pSubTimer = (PRTTIMERLNXSUBTIMER)ulUser; 450 PRTTIMER pTimer = pSubTimer->pParent; 451 452 /* 453 * Don't call the handler if the timer has been suspended. 454 * Also, when running on all CPUS, make sure we don't call out twice 455 * on a CPU because of timer migration. 456 * 457 * For the specific cpu case, we're just ignoring timer migration for now... (bad) 458 */ 459 if ( ASMAtomicUoReadBool(&pTimer->fSuspended) 460 #ifdef CONFIG_SMP 461 || ( pTimer->fAllCpus 462 && (RTCPUID)(pSubTimer - &pTimer->aSubTimers[0]) != RTMpCpuId()) 463 #endif 464 ) 465 rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_ACTIVE); 466 else if (!pTimer->u64NanoInterval) 467 { 468 /* 469 * One shot timer, stop it before dispatching it. 470 */ 471 if (pTimer->cCpus == 1) 472 ASMAtomicWriteBool(&pTimer->fSuspended, true); 473 rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_ACTIVE); 474 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick); 475 } 476 else 477 { 391 478 /* 392 479 * Interval timer, calculate the next timeout and re-arm it. 393 480 * 394 * The first time around, we'll re-adjust the u 64StartTS to481 * The first time around, we'll re-adjust the u.Std.u64StartTS to 395 482 * try prevent some jittering if we were started at a bad time. 396 483 * This may of course backfire with highres timers... 484 * 485 * Note! u64NanoInterval won't change for standard timers. 397 486 */ 487 const uint64_t iTick = ++pSubTimer->iTick; 488 const uint64_t u64NanoInterval = pTimer->u64NanoInterval; 489 const uint64_t u64NanoTS = RTTimeNanoTS(); 490 398 491 if (RT_UNLIKELY(iTick == 1)) 399 492 { 400 pSubTimer->u64StartTS = pSubTimer->u64NextTS = u64NanoTS; 401 pSubTimer->ulNextJiffies = jiffies; 493 pSubTimer->u.Std.u64StartTS = u64NanoTS; 494 pSubTimer->u.Std.u64NextTS = u64NanoTS; 495 pSubTimer->u.Std.ulNextJiffies = jiffies; 402 496 } 403 497 404 pSubTimer->u 64NextTS += pTimer->u64NanoInterval;498 pSubTimer->u.Std.u64NextTS += u64NanoInterval; 405 499 if (pTimer->cJiffies) 406 500 { 407 pSubTimer->u lNextJiffies += pTimer->cJiffies;501 pSubTimer->u.Std.ulNextJiffies += pTimer->cJiffies; 408 502 /* Prevent overflows when the jiffies counter wraps around. 409 503 * Special thanks to Ken Preslan for helping debugging! */ 410 while (time_before(pSubTimer->u lNextJiffies, jiffies))504 while (time_before(pSubTimer->u.Std.ulNextJiffies, jiffies)) 411 505 { 412 pSubTimer->u lNextJiffies += pTimer->cJiffies;413 pSubTimer->u 64NextTS += pTimer->u64NanoInterval;506 pSubTimer->u.Std.ulNextJiffies += pTimer->cJiffies; 507 pSubTimer->u.Std.u64NextTS += u64NanoInterval; 414 508 } 415 509 } 416 510 else 417 511 { 418 while (pSubTimer->u 64NextTS < u64NanoTS)419 pSubTimer->u 64NextTS += pTimer->u64NanoInterval;420 pSubTimer->u lNextJiffies = jiffies + rtTimerLnxNanoToJiffies(pSubTimer->u64NextTS - u64NanoTS);512 while (pSubTimer->u.Std.u64NextTS < u64NanoTS) 513 pSubTimer->u.Std.u64NextTS += u64NanoInterval; 514 pSubTimer->u.Std.ulNextJiffies = jiffies + rtTimerLnxNanoToJiffies(pSubTimer->u.Std.u64NextTS - u64NanoTS); 421 515 } 422 516 423 517 # ifdef CONFIG_SMP 424 518 if (pTimer->fSpecificCpu || pTimer->fAllCpus) 425 mod_timer_pinned(&pSubTimer-> LnxTimer, pSubTimer->ulNextJiffies);519 mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies); 426 520 else 427 521 # endif 428 mod_timer(&pSubTimer->LnxTimer, pSubTimer->ulNextJiffies); 429 #endif 522 mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies); 430 523 431 524 /* … … 434 527 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 435 528 } 436 437 #ifdef RT_USE_LINUX_HRTIMER 438 return rc; 439 #endif 440 } 529 } 530 #endif /* !RTTIMER_LINUX_ONLY_HRTIMER */ 531 441 532 442 533 … … 455 546 PRTTIMER pTimer = (PRTTIMER)pvUser1; 456 547 Assert(idCpu < pTimer->cCpus); 457 rtTimerLnxStartSubTimer(&pTimer->aSubTimers[idCpu], pArgs->u64Now, pArgs->u64First, true /*fPinned*/ );548 rtTimerLnxStartSubTimer(&pTimer->aSubTimers[idCpu], pArgs->u64Now, pArgs->u64First, true /*fPinned*/, pTimer->fHighRes); 458 549 } 459 550 … … 607 698 PRTTIMERLNXSUBTIMER pSubTimer = &pTimer->aSubTimers[idCpu]; 608 699 if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STARTING, RTTIMERLNXSTATE_STOPPED)) 609 rtTimerLnxStartSubTimer(pSubTimer, pArgs->u64Now, pArgs->u64First, true /*fPinned*/ );700 rtTimerLnxStartSubTimer(pSubTimer, pArgs->u64Now, pArgs->u64First, true /*fPinned*/, pTimer->fHighRes); 610 701 } 611 702 … … 660 751 661 752 if (RTMpCpuId() == idCpu) 662 rtTimerLnxStartSubTimer(pSubTimer, Args.u64Now, Args.u64First, true /*fPinned*/ );753 rtTimerLnxStartSubTimer(pSubTimer, Args.u64Now, Args.u64First, true /*fPinned*/, pTimer->fHighRes); 663 754 else 664 755 { … … 708 799 PRTTIMERLINUXSTARTONCPUARGS pArgs = (PRTTIMERLINUXSTARTONCPUARGS)pvUser2; 709 800 PRTTIMER pTimer = (PRTTIMER)pvUser1; 710 rtTimerLnxStartSubTimer(&pTimer->aSubTimers[0], pArgs->u64Now, pArgs->u64First, true /*fPinned*/ );801 rtTimerLnxStartSubTimer(&pTimer->aSubTimers[0], pArgs->u64Now, pArgs->u64First, true /*fPinned*/, pTimer->fHighRes); 711 802 } 712 803 … … 742 833 ASMAtomicWriteBool(&pTimer->fSuspended, false); 743 834 if (!pTimer->fSpecificCpu) 744 rtTimerLnxStartSubTimer(&pTimer->aSubTimers[0], Args.u64Now, Args.u64First, false /*fPinned*/); 835 { 836 rtTimerLnxStartSubTimer(&pTimer->aSubTimers[0], Args.u64Now, Args.u64First, false /*fPinned*/, pTimer->fHighRes); 837 } 745 838 else 746 839 { … … 792 885 793 886 887 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 888 { 889 int rc = VINF_SUCCESS; 890 891 /* 892 * Validate. 893 */ 894 AssertPtrReturn(pTimer, VERR_INVALID_HANDLE); 895 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_HANDLE); 896 AssertReturn(u64NanoInterval, VERR_INVALID_PARAMETER); 897 898 /* 899 * Make the change. 900 */ 901 #ifdef RTTIMER_LINUX_WITH_HRTIMER 902 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 903 if (pTimer->fHighRes) 904 # endif 905 ASMAtomicWriteU64(&pTimer->u64NanoInterval, u64NanoInterval); 906 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 907 else 908 # endif 909 #endif 910 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 911 rc = VERR_NOT_SUPPORTED; /** @todo Implement this if needed. */ 912 #endif 913 914 return rc; 915 } 916 RT_EXPORT_SYMBOL(RTTimerChangeInterval); 917 918 794 919 RTDECL(int) RTTimerDestroy(PRTTIMER pTimer) 795 920 { … … 836 961 837 962 838 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)839 { 840 PRTTIMER pTimer;841 RTCPUID iCpu;842 unsigned cCpus;963 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 964 { 965 PRTTIMER pTimer; 966 RTCPUID iCpu; 967 unsigned cCpus; 843 968 844 969 *ppTimer = NULL; … … 851 976 if ( (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) 852 977 && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL 853 && !RTMpIsCpuOnline(fFlags & RTTIMER_FLAGS_CPU_MASK)) 854 return (fFlags & RTTIMER_FLAGS_CPU_MASK) > RTMpGetMaxCpuId() 855 ? VERR_CPU_NOT_FOUND 856 : VERR_CPU_OFFLINE; 978 && !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK))) 979 return VERR_CPU_NOT_FOUND; 857 980 858 981 /* … … 879 1002 pTimer->hSpinlock = NIL_RTSPINLOCK; 880 1003 pTimer->fSuspended = true; 1004 pTimer->fHighRes = !!(fFlags & RTTIMER_FLAGS_HIGH_RES); 881 1005 #ifdef CONFIG_SMP 882 1006 pTimer->fSpecificCpu = (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL; 883 1007 pTimer->fAllCpus = (fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL; 884 pTimer->idCpu = fFlags & RTTIMER_FLAGS_CPU_MASK;1008 pTimer->idCpu = pTimer->fSpecificCpu ? RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK) : NIL_RTCPUID; 885 1009 #else 886 1010 pTimer->fSpecificCpu = !!(fFlags & RTTIMER_FLAGS_CPU_SPECIFIC); … … 891 1015 pTimer->pvUser = pvUser; 892 1016 pTimer->u64NanoInterval = u64NanoInterval; 893 #ifndef RT _USE_LINUX_HRTIMER1017 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 894 1018 pTimer->cJiffies = u64NanoInterval / RTTimerGetSystemGranularity(); 895 1019 if (pTimer->cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval) … … 899 1023 for (iCpu = 0; iCpu < cCpus; iCpu++) 900 1024 { 901 #ifdef RT_USE_LINUX_HRTIMER 902 hrtimer_init(&pTimer->aSubTimers[iCpu].LnxTimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 903 pTimer->aSubTimers[iCpu].LnxTimer.function = rtTimerLinuxCallback; 904 #else 905 init_timer(&pTimer->aSubTimers[iCpu].LnxTimer); 906 pTimer->aSubTimers[iCpu].LnxTimer.data = (unsigned long)&pTimer->aSubTimers[iCpu]; 907 pTimer->aSubTimers[iCpu].LnxTimer.function = rtTimerLinuxCallback; 908 pTimer->aSubTimers[iCpu].LnxTimer.expires = jiffies; 909 pTimer->aSubTimers[iCpu].u64StartTS = 0; 910 pTimer->aSubTimers[iCpu].u64NextTS = 0; 1025 #ifdef RTTIMER_LINUX_WITH_HRTIMER 1026 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 1027 if (pTimer->fHighRes) 1028 # endif 1029 { 1030 hrtimer_init(&pTimer->aSubTimers[iCpu].u.Hr.LnxTimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 1031 pTimer->aSubTimers[iCpu].u.Hr.LnxTimer.function = rtTimerLinuxHrCallback; 1032 } 1033 # ifndef RTTIMER_LINUX_ONLY_HRTIMER 1034 else 1035 # endif 1036 #endif 1037 #ifndef RTTIMER_LINUX_ONLY_HRTIMER 1038 { 1039 init_timer(&pTimer->aSubTimers[iCpu].u.Std.LnxTimer); 1040 pTimer->aSubTimers[iCpu].u.Std.LnxTimer.data = (unsigned long)&pTimer->aSubTimers[iCpu]; 1041 pTimer->aSubTimers[iCpu].u.Std.LnxTimer.function = rtTimerLinuxStdCallback; 1042 pTimer->aSubTimers[iCpu].u.Std.LnxTimer.expires = jiffies; 1043 pTimer->aSubTimers[iCpu].u.Std.u64StartTS = 0; 1044 pTimer->aSubTimers[iCpu].u.Std.u64NextTS = 0; 1045 } 911 1046 #endif 912 1047 pTimer->aSubTimers[iCpu].iTick = 0; … … 945 1080 RTDECL(uint32_t) RTTimerGetSystemGranularity(void) 946 1081 { 947 #ifdef RT_USE_LINUX_HRTIMER 1082 #ifdef RTTIMER_LINUX_ONLY_HRTIMER 1083 /** @todo Not sure if this is what we want or not... Add new API for 1084 * querying the resolution of the high res timers? */ 948 1085 struct timespec Ts; 949 1086 int rc = hrtimer_get_res(CLOCK_MONOTONIC, &Ts); … … 975 1112 RTDECL(bool) RTTimerCanDoHighResolution(void) 976 1113 { 977 #ifdef RT _USE_LINUX_HRTIMER1114 #ifdef RTTIMER_LINUX_WITH_HRTIMER 978 1115 return true; 979 1116 #else -
trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp
r32504 r32572 218 218 if (!ASMAtomicUoReadBool(&pTimer->fSuspended)) 219 219 return VERR_TIMER_ACTIVE; 220 if ( pTimer->fSpecificCpu 221 && !RTMpIsCpuOnline(pTimer->idCpu)) 222 return VERR_CPU_OFFLINE; 220 223 221 224 /* … … 291 294 292 295 296 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 297 { 298 AssertPtrReturn(pTimer, VERR_INVALID_HANDLE); 299 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_HANDLE); 300 301 return VERR_NOT_SUPPORTED; 302 } 303 304 293 305 RTDECL(int) RTTimerDestroy(PRTTIMER pTimer) 294 306 { … … 300 312 301 313 /* 302 * Invalidate the timer, stop it if it's running and finally .314 * Invalidate the timer, stop it if it's running and finally 303 315 * free up the memory. 304 316 */ … … 312 324 313 325 314 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)326 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 315 327 { 316 328 *ppTimer = NULL; … … 323 335 if ( (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) 324 336 && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL 325 && !RTMpIsCpuOnline(fFlags & RTTIMER_FLAGS_CPU_MASK)) 326 return (fFlags & RTTIMER_FLAGS_CPU_MASK) > RTMpGetMaxCpuId() 327 ? VERR_CPU_NOT_FOUND 328 : VERR_CPU_OFFLINE; 337 && !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK))) 338 return VERR_CPU_NOT_FOUND; 329 339 330 340 /* … … 349 359 pTimer->fSpecificCpu = (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL; 350 360 pTimer->fOmniTimer = (fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL; 351 pTimer->idCpu = fFlags & RTTIMER_FLAGS_CPU_MASK;361 pTimer->idCpu = pTimer->fSpecificCpu ? RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK) : NIL_RTCPUID; 352 362 pTimer->cSubTimers = cSubTimers; 353 363 pTimer->pfnTimer = pfnTimer; … … 362 372 * ASSUMES that no cpus will ever go offline. 363 373 */ 364 pTimer->idCpu = NIL_RTCPUID; /* */374 pTimer->idCpu = NIL_RTCPUID; 365 375 for (unsigned iCpu = 0; iCpu < cSubTimers; iCpu++) 366 376 { -
trunk/src/VBox/Runtime/r0drv/os2/timer-r0drv-os2.cpp
r32504 r32572 109 109 110 110 111 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)111 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 112 112 { 113 113 *ppTimer = NULL; … … 289 289 290 290 291 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 292 { 293 if (!rtTimerIsValid(pTimer)) 294 return VERR_INVALID_HANDLE; 295 296 return VERR_NOT_SUPPORTED; 297 } 298 299 291 300 DECLASM(void) rtTimerOs2Tick(void) 292 301 { -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/timer-r0drv-solaris.c
r32504 r32572 103 103 104 104 105 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)105 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 106 106 { 107 107 RT_ASSERT_PREEMPTIBLE(); … … 118 118 if ( (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) 119 119 && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL 120 && !RTMpIsCpuPossible( (fFlags & RTTIMER_FLAGS_CPU_MASK)))120 && !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK))) 121 121 return VERR_CPU_NOT_FOUND; 122 122 … … 143 143 pTimer->fAllCpu = false; 144 144 pTimer->fSpecificCpu = true; 145 pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK; 145 pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK; /* ASSUMES: index == cpuid */ 146 146 } 147 147 else … … 237 237 238 238 239 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 240 { 241 RTTIMER_ASSERT_VALID_RET(pTimer); 242 243 /** @todo implement me! */ 244 245 return VERR_NOT_SUPPORTED; 246 } 247 248 239 249 RTDECL(uint32_t) RTTimerGetSystemGranularity(void) 240 250 { … … 257 267 RTDECL(bool) RTTimerCanDoHighResolution(void) 258 268 { 259 return true; 260 } 261 269 /** @todo return true; - when missing bits have been implemented and tested*/ 270 return false; 271 } 272 -
trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp
r28800 r32572 397 397 398 398 399 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, u nsignedfFlags, PFNRTTIMER pfnTimer, void *pvUser)399 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 400 400 { 401 401 /* … … 811 811 } 812 812 813 814 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 815 { 816 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 817 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 818 return VERR_NOT_SUPPORTED; 819 } 820 -
trunk/src/VBox/VMM/VMMAll/TMAll.cpp
r32489 r32572 2374 2374 /* Fudge factor. */ 2375 2375 /** @todo make this configurable. */ 2376 #if 0 /* what's wrong with this expression? I end up with uHz = 0 after this multiplication... */ 2376 2377 uHz *= 110 + pVCpu->idCpu == pVM->tm.s.idTimerCpu; 2378 #else 2379 if (pVCpu->idCpu == pVM->tm.s.idTimerCpu) 2380 uHz *= 111; 2381 else 2382 uHz *= 110; 2383 #endif 2377 2384 uHz /= 100; 2378 2385 2386 //LogAlways(("TMCalcHostTimerFrequency->%u\n", uHz)); 2379 2387 return uHz; 2380 2388 } -
trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
r32489 r32572 57 57 #include <iprt/memobj.h> 58 58 #include <iprt/mp.h> 59 #include <iprt/cpuset.h> 60 #include <iprt/spinlock.h> 61 #include <iprt/timer.h> 62 63 64 /******************************************************************************* 65 * Defined Constants And Macros * 66 *******************************************************************************/ 67 #ifdef DOXYGEN_RUNNING 68 /** Define this to enable the periodic preemption timer. */ 69 # define GVMM_SCHED_WITH_PPT 70 #endif 59 71 60 72 … … 97 109 # define GVMM_MAX_HANDLES 128 98 110 #endif 111 112 /** 113 * Per host CPU GVMM data. 114 */ 115 typedef struct GVMMHOSTCPU 116 { 117 /** Magic number (GVMMHOSTCPU_MAGIC). */ 118 uint32_t volatile u32Magic; 119 /** The CPU ID. */ 120 RTCPUID idCpu; 121 /** The CPU set index. */ 122 uint32_t idxCpuSet; 123 124 #ifdef GVMM_SCHED_WITH_PPT 125 /** Periodic preemption timer data. */ 126 struct 127 { 128 /** The handle to the periodic preemption timer. */ 129 PRTTIMER pTimer; 130 /** Spinlock protecting the data below. */ 131 RTSPINLOCK hSpinlock; 132 /** The smalles Hz that we need to care about. (static) */ 133 uint32_t uMinHz; 134 /** The number of ticks between each historization. */ 135 uint32_t cTicksHistoriziationInterval; 136 /** The current historization tick (counting up to 137 * cTicksHistoriziationInterval and then resetting). */ 138 uint32_t iTickHistorization; 139 /** The current timer interval. This is set to 0 when inactive. */ 140 uint32_t cNsInterval; 141 /** The current timer frequency. This is set to 0 when inactive. */ 142 uint32_t uTimerHz; 143 /** The current max frequency reported by the EMTs. 144 * This gets historicize and reset by the timer callback. This is 145 * read without holding the spinlock, so needs atomic updating. */ 146 uint32_t volatile uDesiredHz; 147 /** Whether the timer was started or not. */ 148 bool volatile fStarted; 149 /** Set if we're starting timer. */ 150 bool volatile fStarting; 151 /** The index of the next history entry (mod it). */ 152 uint32_t iHzHistory; 153 /** Hitoricized uDesiredHz values. The array wraps around, new entries 154 * are added at iHzHistory. This is updated approximately every 155 * GVMMHOSTCPU_PPT_HIST_INTERVAL_NS by the timer callback. */ 156 uint32_t aHzHistory[32]; 157 /** Statistics counter for recording the number of interval changes. */ 158 uint64_t cChanges; 159 /** Statistics counter for recording the number of timer starts. */ 160 uint64_t cStarts; 161 } Ppt; 162 #endif /* GVMM_SCHED_WITH_PPT */ 163 164 } GVMMHOSTCPU; 165 /** Pointer to the per host CPU GVMM data. */ 166 typedef GVMMHOSTCPU *PGVMMHOSTCPU; 167 /** The GVMMHOSTCPU::u32Magic value (Petra, Tanya & Rachel Haden). */ 168 #define GVMMHOSTCPU_MAGIC UINT32_C(0x19711011) 169 /** The interval on history entry should cover (approximately) give in 170 * nanoseconds. */ 171 #define GVMMHOSTCPU_PPT_HIST_INTERVAL_NS UINT32_C(20000000) 172 99 173 100 174 /** … … 148 222 */ 149 223 uint32_t nsEarlyWakeUp2; 224 225 /** The number of entries in the host CPU array (aHostCpus). */ 226 uint32_t cHostCpus; 227 /** Per host CPU data (variable length). */ 228 GVMMHOSTCPU aHostCpus[1]; 150 229 } GVMM; 151 230 /** Pointer to the GVMM instance data. */ … … 198 277 static int gvmmR0ByVM(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM, bool fTakeUsedLock); 199 278 static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM); 279 #ifdef GVMM_SCHED_WITH_PPT 280 static DECLCALLBACK(void) gvmmR0SchedPeriodicPreemptionTimerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 281 #endif 200 282 201 283 … … 214 296 * Allocate and initialize the instance data. 215 297 */ 216 PGVMM pGVMM = (PGVMM)RTMemAllocZ(sizeof(*pGVMM)); 298 uint32_t cHostCpus = RTMpGetArraySize(); 299 AssertMsgReturn(cHostCpus > 0 && cHostCpus < _64K, ("%d", (int)cHostCpus), VERR_INTERNAL_ERROR_2); 300 301 PGVMM pGVMM = (PGVMM)RTMemAllocZ(RT_UOFFSETOF(GVMM, aHostCpus[cHostCpus])); 217 302 if (!pGVMM) 218 303 return VERR_NO_MEMORY; … … 250 335 pGVMM->nsEarlyWakeUp2 = 50000 /* ns (0.050 ms) */; 251 336 252 g_pGVMM = pGVMM; 253 LogFlow(("GVMMR0Init: pGVMM=%p\n", pGVMM)); 254 return VINF_SUCCESS; 255 } 256 337 /* The host CPU data. */ 338 pGVMM->cHostCpus = cHostCpus; 339 uint32_t iCpu = cHostCpus; 340 RTCPUSET PossibleSet; 341 RTMpGetSet(&PossibleSet); 342 while (iCpu-- > 0) 343 { 344 pGVMM->aHostCpus[iCpu].idxCpuSet = iCpu; 345 #ifdef GVMM_SCHED_WITH_PPT 346 pGVMM->aHostCpus[iCpu].Ppt.pTimer = NULL; 347 pGVMM->aHostCpus[iCpu].Ppt.hSpinlock = NIL_RTSPINLOCK; 348 pGVMM->aHostCpus[iCpu].Ppt.uMinHz = 5; /** @todo Add some API which figures this one out. (not *that* important) */ 349 pGVMM->aHostCpus[iCpu].Ppt.cTicksHistoriziationInterval = 1; 350 //pGVMM->aHostCpus[iCpu].Ppt.iTickHistorization = 0; 351 //pGVMM->aHostCpus[iCpu].Ppt.cNsInterval = 0; 352 //pGVMM->aHostCpus[iCpu].Ppt.uTimerHz = 0; 353 //pGVMM->aHostCpus[iCpu].Ppt.uDesiredHz = 0; 354 //pGVMM->aHostCpus[iCpu].Ppt.fStarted = false; 355 //pGVMM->aHostCpus[iCpu].Ppt.fStarting = false; 356 //pGVMM->aHostCpus[iCpu].Ppt.iHzHistory = 0; 357 //pGVMM->aHostCpus[iCpu].Ppt.aHzHistory = {0}; 358 #endif 359 360 if (RTCpuSetIsMember(&PossibleSet, iCpu)) 361 { 362 pGVMM->aHostCpus[iCpu].idCpu = RTMpCpuIdFromSetIndex(iCpu); 363 pGVMM->aHostCpus[iCpu].u32Magic = GVMMHOSTCPU_MAGIC; 364 365 #ifdef GVMM_SCHED_WITH_PPT 366 rc = RTTimerCreateEx(&pGVMM->aHostCpus[iCpu].Ppt.pTimer, 367 50*1000*1000 /* whatever */, 368 RTTIMER_FLAGS_CPU(iCpu) | RTTIMER_FLAGS_HIGH_RES, 369 gvmmR0SchedPeriodicPreemptionTimerCallback, 370 &pGVMM->aHostCpus[iCpu]); 371 if (RT_SUCCESS(rc)) 372 rc = RTSpinlockCreate(&pGVMM->aHostCpus[iCpu].Ppt.hSpinlock); 373 if (RT_FAILURE(rc)) 374 { 375 while (iCpu < cHostCpus) 376 { 377 RTTimerDestroy(pGVMM->aHostCpus[iCpu].Ppt.pTimer); 378 RTSpinlockDestroy(pGVMM->aHostCpus[iCpu].Ppt.hSpinlock); 379 pGVMM->aHostCpus[iCpu].Ppt.hSpinlock = NIL_RTSPINLOCK; 380 iCpu++; 381 } 382 break; 383 } 384 #endif 385 } 386 else 387 { 388 pGVMM->aHostCpus[iCpu].idCpu = NIL_RTCPUID; 389 pGVMM->aHostCpus[iCpu].u32Magic = 0; 390 } 391 } 392 if (RT_SUCCESS(rc)) 393 { 394 g_pGVMM = pGVMM; 395 LogFlow(("GVMMR0Init: pGVMM=%p cHostCpus=%u\n", pGVMM, cHostCpus)); 396 return VINF_SUCCESS; 397 } 398 399 /* bail out. */ 400 RTSemFastMutexDestroy(pGVMM->UsedLock); 401 pGVMM->UsedLock = NIL_RTSEMFASTMUTEX; 402 } 257 403 RTSemFastMutexDestroy(pGVMM->CreateDestroyLock); 404 pGVMM->CreateDestroyLock = NIL_RTSEMFASTMUTEX; 258 405 } 259 406 … … 282 429 } 283 430 284 pGVMM->u32Magic++; 285 431 /* 432 * First of all, stop all active timers. 433 */ 434 uint32_t cActiveTimers = 0; 435 uint32_t iCpu = pGVMM->cHostCpus; 436 while (iCpu-- > 0) 437 { 438 ASMAtomicWriteU32(&pGVMM->aHostCpus[iCpu].u32Magic, ~GVMMHOSTCPU_MAGIC); 439 #ifdef GVMM_SCHED_WITH_PPT 440 if ( pGVMM->aHostCpus[iCpu].Ppt.pTimer != NULL 441 && RT_SUCCESS(RTTimerStop(pGVMM->aHostCpus[iCpu].Ppt.pTimer))) 442 cActiveTimers++; 443 #endif 444 } 445 if (cActiveTimers) 446 RTThreadSleep(1); /* fudge */ 447 448 /* 449 * Invalidate the and free resources. 450 */ 451 pGVMM->u32Magic = ~GVMM_MAGIC; 286 452 RTSemFastMutexDestroy(pGVMM->UsedLock); 287 453 pGVMM->UsedLock = NIL_RTSEMFASTMUTEX; … … 295 461 pGVMM->iUsedHead = 0; 296 462 } 463 464 #ifdef GVMM_SCHED_WITH_PPT 465 iCpu = pGVMM->cHostCpus; 466 while (iCpu-- > 0) 467 { 468 RTTimerDestroy(pGVMM->aHostCpus[iCpu].Ppt.pTimer); 469 pGVMM->aHostCpus[iCpu].Ppt.pTimer = NULL; 470 RTSpinlockDestroy(pGVMM->aHostCpus[iCpu].Ppt.hSpinlock); 471 pGVMM->aHostCpus[iCpu].Ppt.hSpinlock = NIL_RTSPINLOCK; 472 } 473 #endif 297 474 298 475 RTMemFree(pGVMM); … … 1886 2063 1887 2064 2065 #ifdef GVMM_SCHED_WITH_PPT 2066 /** 2067 * Timer callback for the periodic preemption timer. 2068 * 2069 * @param pTimer The timer handle. 2070 * @param pvUser Pointer to the per cpu structure. 2071 * @param iTick The current tick. 2072 */ 2073 static DECLCALLBACK(void) gvmmR0SchedPeriodicPreemptionTimerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 2074 { 2075 PGVMMHOSTCPU pCpu = (PGVMMHOSTCPU)pvUser; 2076 2077 /* 2078 * Termination check 2079 */ 2080 if (pCpu->u32Magic != GVMMHOSTCPU_MAGIC) 2081 return; 2082 2083 /* 2084 * Do the house keeping. 2085 */ 2086 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 2087 RTSpinlockAcquireNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2088 2089 if (++pCpu->Ppt.iTickHistorization >= pCpu->Ppt.cTicksHistoriziationInterval) 2090 { 2091 /* 2092 * Historicize the max frequency. 2093 */ 2094 uint32_t iHzHistory = ++pCpu->Ppt.iHzHistory % RT_ELEMENTS(pCpu->Ppt.aHzHistory); 2095 pCpu->Ppt.aHzHistory[iHzHistory] = pCpu->Ppt.uDesiredHz; 2096 pCpu->Ppt.iTickHistorization = 0; 2097 pCpu->Ppt.uDesiredHz = 0; 2098 2099 /* 2100 * Check if the current timer frequency. 2101 */ 2102 uint32_t uHistMaxHz = 0; 2103 for (uint32_t i = 0; i < RT_ELEMENTS(pCpu->Ppt.aHzHistory); i++) 2104 if (pCpu->Ppt.aHzHistory[i] > uHistMaxHz) 2105 uHistMaxHz = pCpu->Ppt.aHzHistory[i]; 2106 if (uHistMaxHz == pCpu->Ppt.uTimerHz) 2107 RTSpinlockReleaseNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2108 else if (uHistMaxHz) 2109 { 2110 /* 2111 * Reprogram it. 2112 */ 2113 pCpu->Ppt.cChanges++; 2114 pCpu->Ppt.iTickHistorization = 0; 2115 pCpu->Ppt.uTimerHz = uHistMaxHz; 2116 uint32_t const cNsInterval = UINT32_C(1000000000) / uHistMaxHz; 2117 pCpu->Ppt.cNsInterval = cNsInterval; 2118 if (cNsInterval < GVMMHOSTCPU_PPT_HIST_INTERVAL_NS) 2119 pCpu->Ppt.cTicksHistoriziationInterval = ( GVMMHOSTCPU_PPT_HIST_INTERVAL_NS 2120 + GVMMHOSTCPU_PPT_HIST_INTERVAL_NS / 2 - 1) 2121 / cNsInterval; 2122 else 2123 pCpu->Ppt.cTicksHistoriziationInterval = 1; 2124 RTSpinlockReleaseNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2125 2126 /*SUPR0Printf("Cpu%u: change to %u Hz / %u ns\n", pCpu->idxCpuSet, uHistMaxHz, cNsInterval);*/ 2127 RTTimerChangeInterval(pTimer, cNsInterval); 2128 } 2129 else 2130 { 2131 /* 2132 * Stop it. 2133 */ 2134 pCpu->Ppt.fStarted = false; 2135 pCpu->Ppt.uTimerHz = 0; 2136 pCpu->Ppt.cNsInterval = 0; 2137 RTSpinlockReleaseNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2138 2139 /*SUPR0Printf("Cpu%u: stopping (%u Hz)\n", pCpu->idxCpuSet, uHistMaxHz);*/ 2140 RTTimerStop(pTimer); 2141 } 2142 } 2143 else 2144 RTSpinlockReleaseNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2145 } 2146 #endif /* GVMM_SCHED_WITH_PPT */ 2147 1888 2148 1889 2149 /** … … 1891 2151 * 1892 2152 * The caller must have disabled preemption! 2153 * The caller must check that the host can do high resolution timers. 1893 2154 * 1894 2155 * @param pVM The VM handle. … … 1898 2159 GVMMR0DECL(void) GVMMR0SchedUpdatePeriodicPreemptionTimer(PVM pVM, RTCPUID idHostCpu, uint32_t uHz) 1899 2160 { 1900 2161 #ifdef GVMM_SCHED_WITH_PPT 2162 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 2163 Assert(RTTimerCanDoHighResolution()); 2164 2165 /* 2166 * Resolve the per CPU data. 2167 */ 2168 uint32_t iCpu = RTMpCpuIdToSetIndex(idHostCpu); 2169 PGVMM pGVMM = g_pGVMM; 2170 if ( !VALID_PTR(pGVMM) 2171 || pGVMM->u32Magic != GVMM_MAGIC) 2172 return; 2173 AssertMsgReturnVoid(iCpu < pGVMM->cHostCpus, ("iCpu=%d cHostCpus=%d\n", iCpu, pGVMM->cHostCpus)); 2174 PGVMMHOSTCPU pCpu = &pGVMM->aHostCpus[iCpu]; 2175 AssertMsgReturnVoid( pCpu->u32Magic == GVMMHOSTCPU_MAGIC 2176 && pCpu->idCpu == idHostCpu, 2177 ("u32Magic=%#x idCpu=% idHostCpu=%d\n", pCpu->u32Magic, pCpu->idCpu, idHostCpu)); 2178 2179 /* 2180 * Check whether we need to do anything about the timer. 2181 * We have to be a little bit careful since we might be race the timer 2182 * callback here. 2183 */ 2184 if (uHz > 20000) 2185 uHz = 20000; 2186 if (RT_UNLIKELY( uHz > ASMAtomicReadU32(&pCpu->Ppt.uDesiredHz) 2187 && uHz >= pCpu->Ppt.uMinHz 2188 && !pCpu->Ppt.fStarting /* solaris paranoia */)) 2189 { 2190 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 2191 RTSpinlockAcquireNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2192 2193 pCpu->Ppt.uDesiredHz = uHz; 2194 uint32_t cNsInterval = 0; 2195 if (!pCpu->Ppt.fStarted) 2196 { 2197 pCpu->Ppt.cStarts++; 2198 pCpu->Ppt.fStarted = true; 2199 pCpu->Ppt.fStarting = true; 2200 pCpu->Ppt.iTickHistorization = 0; 2201 pCpu->Ppt.uTimerHz = uHz; 2202 pCpu->Ppt.cNsInterval = cNsInterval = UINT32_C(1000000000) / uHz; 2203 if (cNsInterval < GVMMHOSTCPU_PPT_HIST_INTERVAL_NS) 2204 pCpu->Ppt.cTicksHistoriziationInterval = ( GVMMHOSTCPU_PPT_HIST_INTERVAL_NS 2205 + GVMMHOSTCPU_PPT_HIST_INTERVAL_NS / 2 - 1) 2206 / cNsInterval; 2207 else 2208 pCpu->Ppt.cTicksHistoriziationInterval = 1; 2209 } 2210 2211 RTSpinlockReleaseNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2212 2213 if (cNsInterval) 2214 { 2215 RTTimerChangeInterval(pCpu->Ppt.pTimer, cNsInterval); 2216 int rc = RTTimerStart(pCpu->Ppt.pTimer, cNsInterval); 2217 AssertRC(rc); 2218 2219 RTSpinlockAcquireNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2220 if (RT_FAILURE(rc)) 2221 pCpu->Ppt.fStarted = false; 2222 pCpu->Ppt.fStarting = false; 2223 RTSpinlockReleaseNoInts(pCpu->Ppt.hSpinlock, &Tmp); 2224 } 2225 } 2226 #endif /* GVMM_SCHED_WITH_PPT */ 1901 2227 } 1902 2228
Note:
See TracChangeset
for help on using the changeset viewer.