Changeset 55863 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- May 14, 2015 6:29:34 PM (10 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/include/internal/magics.h
r51571 r55863 193 193 /** RTTESTINT::u32Magic value. (Daniel Kehlmann) */ 194 194 #define RTTESTINT_MAGIC UINT32_C(0x19750113) 195 /** RTTHREADCTX INT::u32Magic value. (Dennis MacAlistair Ritchie) */196 #define RTTHREADCTX INT_MAGICUINT32_C(0x19410909)195 /** RTTHREADCTXHOOKINT::u32Magic value. (Dennis MacAlistair Ritchie) */ 196 #define RTTHREADCTXHOOKINT_MAGIC UINT32_C(0x19410909) 197 197 /** RTTHREADINT::u32Magic value. (Gilbert Keith Chesterton) */ 198 198 #define RTTHREADINT_MAGIC UINT32_C(0x18740529) -
trunk/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp
r47572 r55863 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Thread -Context Hooks, Ring-0 Driver, Generic.3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Generic. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2013 Oracle Corporation7 * Copyright (C) 2013-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 34 34 #include "internal/iprt.h" 35 35 36 RTDECL(int) RTThreadCtxHook sCreate(PRTTHREADCTX phThreadCtx)36 RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser) 37 37 { 38 NOREF(phThreadCtx); 39 return VERR_NOT_SUPPORTED; 40 } 41 RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate); 42 43 44 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 45 { 46 NOREF(hThreadCtx); 47 return UINT32_MAX; 48 } 49 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); 50 51 52 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 53 { 54 NOREF(hThreadCtx); 55 return UINT32_MAX; 56 } 57 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); 58 59 60 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser) 61 { 62 NOREF(hThreadCtx); 38 NOREF(phCtxHook); 63 39 NOREF(pfnCallback); 64 40 NOREF(pvUser); 65 41 return VERR_NOT_SUPPORTED; 66 42 } 67 RT_EXPORT_SYMBOL(RTThreadCtxHook sRegister);43 RT_EXPORT_SYMBOL(RTThreadCtxHookCreate); 68 44 69 45 70 RTDECL(int) RTThreadCtxHook sDeregister(RTTHREADCTX hThreadCtx)46 RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook) 71 47 { 72 NOREF(hThreadCtx); 48 return hCtxHook == NIL_RTTHREADCTXHOOK ? VINF_SUCCESS : VERR_INVALID_HANDLE; 49 } 50 RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy); 51 52 53 RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook) 54 { 55 NOREF(hCtxHook); 73 56 return VERR_NOT_SUPPORTED; 74 57 } 75 RT_EXPORT_SYMBOL(RTThreadCtxHook sDeregister);58 RT_EXPORT_SYMBOL(RTThreadCtxHookEnable); 76 59 77 60 78 RTDECL( bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)61 RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook) 79 62 { 80 NOREF(hThreadCtx); 63 NOREF(hCtxHook); 64 return VERR_NOT_SUPPORTED; 65 } 66 RT_EXPORT_SYMBOL(RTThreadCtxHookDisable); 67 68 69 RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook) 70 { 71 NOREF(hCtxHook); 81 72 return false; 82 73 } 83 RT_EXPORT_SYMBOL(RTThreadCtxHook sAreRegistered);74 RT_EXPORT_SYMBOL(RTThreadCtxHookIsEnabled); 84 75 -
trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c
r54872 r55863 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Thread -ContextHook, Ring-0 Driver, Linux.3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Linux. 4 4 */ 5 5 … … 42 42 #include "internal/thread.h" 43 43 44 44 45 /* 45 * Linux kernel 2.6.23 introduced thread-context hooks but RedHat 2.6.18 kernels46 * Linux kernel 2.6.23 introduced preemption notifiers but RedHat 2.6.18 kernels 46 47 * got it backported. 47 48 */ … … 52 53 *******************************************************************************/ 53 54 /** 54 * The internal thread-context object.55 */ 56 typedef struct RTTHREADCTX INT57 { 58 /** Magic value (RTTHREADCTX INT_MAGIC). */55 * The internal hook object for linux. 56 */ 57 typedef struct RTTHREADCTXHOOKINT 58 { 59 /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */ 59 60 uint32_t volatile u32Magic; 60 /** The thread handle (owner) for which the context-hooks areregistered. */61 /** The thread handle (owner) for which the hook is registered. */ 61 62 RTNATIVETHREAD hOwner; 62 63 /** The preemption notifier object. */ 63 struct preempt_notifier hPreemptNotifier; 64 /** Whether this handle has any hooks registered or not. */ 65 bool fRegistered; 66 /** Pointer to the registered thread-context hook. */ 67 PFNRTTHREADCTXHOOK pfnThreadCtxHook; 68 /** User argument passed to the thread-context hook. */ 64 struct preempt_notifier LnxPreemptNotifier; 65 /** Whether the hook is enabled or not. If enabled, the LnxPreemptNotifier 66 * is linked into the owning thread's list of preemption callouts. */ 67 bool fEnabled; 68 /** Pointer to the user callback. */ 69 PFNRTTHREADCTXHOOK pfnCallback; 70 /** User argument passed to the callback. */ 69 71 void *pvUser; 70 /** The thread-context operations. */ 71 struct preempt_ops hPreemptOps; 72 /** The reference count for this object. */ 73 uint32_t volatile cRefs; 72 /** The linux callbacks. */ 73 struct preempt_ops PreemptOps; 74 74 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 19) && defined(RT_ARCH_AMD64) 75 75 /** Starting with 3.1.19, the linux kernel doesn't restore kernel RFLAGS during … … 77 77 RTCCUINTREG fSavedRFlags; 78 78 #endif 79 } RTTHREADCTXINT, *PRTTHREADCTXINT; 79 } RTTHREADCTXHOOKINT; 80 typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT; 80 81 81 82 82 83 /** 83 * Hook function for the thread -preemptingevent.84 * Hook function for the thread schedule out event. 84 85 * 85 86 * @param pPreemptNotifier Pointer to the preempt_notifier struct. 86 * @param pNext Pointer to the task that is preempting the87 * current thread.87 * @param pNext Pointer to the task that is being scheduled 88 * instead of the current thread. 88 89 * 89 90 * @remarks Called with the rq (runqueue) lock held and with preemption and … … 92 93 static void rtThreadCtxHooksLnxSchedOut(struct preempt_notifier *pPreemptNotifier, struct task_struct *pNext) 93 94 { 94 PRTTHREADCTX INT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);95 PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier); 95 96 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 96 97 RTCCUINTREG fSavedEFlags = ASMGetFlags(); … … 99 100 100 101 AssertPtr(pThis); 101 AssertPtr(pThis->pfn ThreadCtxHook);102 Assert(pThis->f Registered);102 AssertPtr(pThis->pfnCallback); 103 Assert(pThis->fEnabled); 103 104 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 104 105 105 pThis->pfn ThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);106 pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser); 106 107 107 108 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) … … 115 116 116 117 /** 117 * Hook function for the thread -resumedevent.118 * Hook function for the thread schedule in event. 118 119 * 119 120 * @param pPreemptNotifier Pointer to the preempt_notifier struct. 120 * @param iCpu The CPU this thread is scheduled on.121 * @param iCpu The CPU this thread is being scheduled on. 121 122 * 122 123 * @remarks Called without holding the rq (runqueue) lock and with preemption 123 124 * enabled! 125 * @todo r=bird: Preemption is of course disabled when it is called. 124 126 */ 125 127 static void rtThreadCtxHooksLnxSchedIn(struct preempt_notifier *pPreemptNotifier, int iCpu) 126 128 { 127 PRTTHREADCTX INT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);129 PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier); 128 130 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 129 131 RTCCUINTREG fSavedEFlags = ASMGetFlags(); … … 132 134 133 135 AssertPtr(pThis); 134 AssertPtr(pThis->pfn ThreadCtxHook);135 Assert(pThis->f Registered);136 137 pThis->pfn ThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);136 AssertPtr(pThis->pfnCallback); 137 Assert(pThis->fEnabled); 138 139 pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser); 138 140 139 141 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) … … 152 154 * @param pThis Pointer to the internal thread-context object. 153 155 */ 154 DECLINLINE(void) rtThreadCtxHooksDeregister(PRTTHREADCTXINT pThis) 155 { 156 preempt_notifier_unregister(&pThis->hPreemptNotifier); 157 pThis->hPreemptOps.sched_out = NULL; 158 pThis->hPreemptOps.sched_in = NULL; 159 pThis->fRegistered = false; 160 } 161 162 163 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx) 164 { 165 PRTTHREADCTXINT pThis; 156 DECLINLINE(void) rtThreadCtxHookDisable(PRTTHREADCTXHOOKINT pThis) 157 { 158 Assert(pThis->PreemptOps.sched_out == rtThreadCtxHooksLnxSchedOut); 159 Assert(pThis->PreemptOps.sched_in == rtThreadCtxHooksLnxSchedIn); 160 preempt_disable(); 161 preempt_notifier_unregister(&pThis->LnxPreemptNotifier); 162 pThis->fEnabled = false; 163 preempt_enable(); 164 } 165 166 167 RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser) 168 { 169 /* 170 * Validate input. 171 */ 172 PRTTHREADCTXHOOKINT pThis; 166 173 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 167 168 pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis)); 174 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); 175 AssertReturn(fFlags == 0, VERR_INVALID_FLAGS); 176 177 /* 178 * Allocate and initialize a new hook. We don't register it yet, just 179 * create it. 180 */ 181 pThis = (PRTTHREADCTXHOOKINT)RTMemAllocZ(sizeof(*pThis)); 169 182 if (RT_UNLIKELY(!pThis)) 170 183 return VERR_NO_MEMORY; 171 pThis->u32Magic = RTTHREADCTXINT_MAGIC; 172 pThis->hOwner = RTThreadNativeSelf(); 173 pThis->fRegistered = false; 174 preempt_notifier_init(&pThis->hPreemptNotifier, &pThis->hPreemptOps); 175 pThis->cRefs = 1; 176 177 *phThreadCtx = pThis; 184 pThis->u32Magic = RTTHREADCTXHOOKINT_MAGIC; 185 pThis->hOwner = RTThreadNativeSelf(); 186 pThis->fEnabled = false; 187 pThis->pfnCallback = pfnCallback; 188 pThis->pvUser = pvUser; 189 preempt_notifier_init(&pThis->LnxPreemptNotifier, &pThis->PreemptOps); 190 pThis->PreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut; 191 pThis->PreemptOps.sched_in = rtThreadCtxHooksLnxSchedIn; 192 193 *phCtxHook = pThis; 178 194 return VINF_SUCCESS; 179 195 } 180 RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate); 181 182 183 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 184 { 185 /* 186 * Validate input. 187 */ 188 uint32_t cRefs; 189 PRTTHREADCTXINT pThis = hThreadCtx; 190 AssertPtr(pThis); 191 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 192 UINT32_MAX); 193 194 cRefs = ASMAtomicIncU32(&pThis->cRefs); 195 Assert(cRefs < UINT32_MAX / 2); 196 return cRefs; 197 } 198 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); 199 200 201 202 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 203 { 204 /* 205 * Validate input. 206 */ 207 uint32_t cRefs; 208 PRTTHREADCTXINT pThis = hThreadCtx; 209 if (pThis == NIL_RTTHREADCTX) 210 return 0; 211 212 AssertPtr(pThis); 213 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 214 UINT32_MAX); 196 RT_EXPORT_SYMBOL(RTThreadCtxHookCreate); 197 198 199 RTDECL(int ) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook) 200 { 201 /* 202 * Validate input. 203 */ 204 PRTTHREADCTXHOOKINT pThis = hCtxHook; 205 if (pThis == NIL_RTTHREADCTXHOOK) 206 return VINF_SUCCESS; 207 AssertPtr(pThis); 208 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 209 VERR_INVALID_HANDLE); 215 210 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 216 217 cRefs = ASMAtomicDecU32(&pThis->cRefs); 218 if (!cRefs) 211 Assert(pThis->fEnabled || pThis->hOwner == RTThreadNativeSelf()); 212 213 /* 214 * If there's still a registered thread-context hook, deregister it now before destroying the object. 215 */ 216 if (pThis->fEnabled) 219 217 { 220 /* 221 * If there's still a registered thread-context hook, deregister it now before destroying the object. 222 */ 223 if (pThis->fRegistered) 224 rtThreadCtxHooksDeregister(pThis); 225 226 /* 227 * Paranoia... but since these are ring-0 threads we can't be too careful. 228 */ 229 Assert(!pThis->fRegistered); 230 Assert(!pThis->hPreemptOps.sched_out); 231 Assert(!pThis->hPreemptOps.sched_in); 232 233 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); 234 RTMemFree(pThis); 218 Assert(pThis->hOwner == RTThreadNativeSelf()); 219 rtThreadCtxHookDisable(pThis); 220 Assert(!pThis->fEnabled); /* paranoia */ 235 221 } 236 else 237 Assert(cRefs < UINT32_MAX / 2); 238 239 return cRefs; 240 } 241 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); 242 243 244 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser) 245 { 246 /* 247 * Validate input. 248 */ 249 PRTTHREADCTXINT pThis = hThreadCtx; 250 if (pThis == NIL_RTTHREADCTX) 251 return VERR_INVALID_HANDLE; 252 AssertPtr(pThis); 253 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 222 223 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC); 224 RTMemFree(pThis); 225 226 return VINF_SUCCESS; 227 } 228 RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy); 229 230 231 RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook) 232 { 233 /* 234 * Validate input. 235 */ 236 PRTTHREADCTXHOOKINT pThis = hCtxHook; 237 AssertPtr(pThis); 238 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 254 239 VERR_INVALID_HANDLE); 255 240 Assert(pThis->hOwner == RTThreadNativeSelf()); 256 Assert(!pThis->hPreemptOps.sched_out); 257 Assert(!pThis->hPreemptOps.sched_in); 258 259 /* 260 * Register the callback. 261 */ 262 pThis->hPreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut; 263 pThis->hPreemptOps.sched_in = rtThreadCtxHooksLnxSchedIn; 264 pThis->pvUser = pvUser; 265 pThis->pfnThreadCtxHook = pfnThreadCtxHook; 266 pThis->fRegistered = true; 267 preempt_notifier_register(&pThis->hPreemptNotifier); 241 Assert(!pThis->fEnabled); 242 if (!pThis->fEnabled) 243 { 244 Assert(pThis->PreemptOps.sched_out == rtThreadCtxHooksLnxSchedOut); 245 Assert(pThis->PreemptOps.sched_in == rtThreadCtxHooksLnxSchedIn); 246 247 /* 248 * Register the callback. 249 */ 250 preempt_disable(); 251 pThis->fEnabled = true; 252 preempt_notifier_register(&pThis->LnxPreemptNotifier); 253 preempt_enable(); 254 } 268 255 269 256 return VINF_SUCCESS; 270 257 } 271 RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister); 272 273 274 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx) 275 { 276 /* 277 * Validate input. 278 */ 279 PRTTHREADCTXINT pThis = hThreadCtx; 280 if (pThis == NIL_RTTHREADCTX) 281 return VERR_INVALID_HANDLE; 282 AssertPtr(pThis); 283 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 284 VERR_INVALID_HANDLE); 285 Assert(pThis->hOwner == RTThreadNativeSelf()); 286 Assert(pThis->fRegistered); 287 288 /* 289 * Deregister the callback. 290 */ 291 rtThreadCtxHooksDeregister(pThis); 258 RT_EXPORT_SYMBOL(RTThreadCtxHookEnable); 259 260 261 RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook) 262 { 263 /* 264 * Validate input. 265 */ 266 PRTTHREADCTXHOOKINT pThis = hCtxHook; 267 if (pThis != NIL_RTTHREADCTXHOOK) 268 { 269 AssertPtr(pThis); 270 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 271 VERR_INVALID_HANDLE); 272 Assert(pThis->hOwner == RTThreadNativeSelf()); 273 274 /* 275 * Deregister the callback. 276 */ 277 if (pThis->fEnabled) 278 rtThreadCtxHookDisable(pThis); 279 } 292 280 return VINF_SUCCESS; 293 281 } 294 RT_EXPORT_SYMBOL(RTThreadCtxHook sDeregister);295 296 297 RTDECL(bool) RTThreadCtxHook sAreRegistered(RTTHREADCTX hThreadCtx)298 { 299 /* 300 * Validate input. 301 */ 302 PRTTHREADCTX INT pThis = hThreadCtx;303 if (pThis == NIL_RTTHREADCTX )282 RT_EXPORT_SYMBOL(RTThreadCtxHookDisable); 283 284 285 RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook) 286 { 287 /* 288 * Validate input. 289 */ 290 PRTTHREADCTXHOOKINT pThis = hCtxHook; 291 if (pThis == NIL_RTTHREADCTXHOOK) 304 292 return false; 305 293 AssertPtr(pThis); 306 AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis)); 307 308 return pThis->fRegistered; 294 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 295 false); 296 297 return pThis->fEnabled; 309 298 } 310 299 311 300 #else /* Not supported / Not needed */ 312 313 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx) 314 { 315 NOREF(phThreadCtx); 316 return VERR_NOT_SUPPORTED; 317 } 318 RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate); 319 320 321 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 322 { 323 NOREF(hThreadCtx); 324 return UINT32_MAX; 325 } 326 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); 327 328 329 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 330 { 331 NOREF(hThreadCtx); 332 return UINT32_MAX; 333 } 334 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); 335 336 337 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser) 338 { 339 NOREF(hThreadCtx); 340 NOREF(pfnThreadCtxHook); 341 NOREF(pvUser); 342 return VERR_NOT_SUPPORTED; 343 } 344 RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister); 345 346 347 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx) 348 { 349 NOREF(hThreadCtx); 350 return VERR_NOT_SUPPORTED; 351 } 352 RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister); 353 354 355 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx) 356 { 357 NOREF(hThreadCtx); 358 return false; 359 } 360 RT_EXPORT_SYMBOL(RTThreadCtxHooksAreRegistered); 361 301 # include "../generic/threadctxhooks-r0drv-generic.cpp" 362 302 #endif /* Not supported / Not needed */ 363 303 -
trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c
r55860 r55863 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Thread -ContextHook, Ring-0 Driver, Solaris.3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Solaris. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2013 Oracle Corporation7 * Copyright (C) 2013-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 45 45 *******************************************************************************/ 46 46 /** 47 * The internal thread-context object.48 */ 49 typedef struct RTTHREADCTX INT50 { 51 /** Magic value (RTTHREADCTX INT_MAGIC). */47 * The internal hook object for solaris. 48 */ 49 typedef struct RTTHREADCTXHOOKINT 50 { 51 /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */ 52 52 uint32_t volatile u32Magic; 53 53 /** The thread handle (owner) for which the context-hooks are registered. */ 54 54 RTNATIVETHREAD hOwner; 55 /** Pointer to the registered thread-context hook. */56 PFNRTTHREADCTXHOOK pfn ThreadCtxHook;57 /** User argument passed to the thread-context hook. */55 /** Pointer to the registered callback function. */ 56 PFNRTTHREADCTXHOOK pfnCallback; 57 /** User argument passed to the callback function. */ 58 58 void *pvUser; 59 /** Whether th is handle has any hooks registered or not. */60 bool volatile f Registered;59 /** Whether the hook is enabled or not. */ 60 bool volatile fEnabled; 61 61 /** Number of references to this object. */ 62 62 uint32_t volatile cRefs; 63 } RTTHREADCTXINT, *PRTTHREADCTXINT; 63 } RTTHREADCTXHOOKINT; 64 typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT; 64 65 65 66 … … 67 68 * Defined Constants And Macros * 68 69 *******************************************************************************/ 69 /** Validates a thread-contexthook handle and returns rc if not valid. */70 /** Validates a hook handle and returns rc if not valid. */ 70 71 #define RTTHREADCTX_VALID_RETURN_RC(pThis, rc) \ 71 72 do { \ 72 73 AssertPtrReturn((pThis), (rc)); \ 73 AssertReturn((pThis)->u32Magic == RTTHREADCTX INT_MAGIC, (rc)); \74 AssertReturn((pThis)->u32Magic == RTTHREADCTXHOOKINT_MAGIC, (rc)); \ 74 75 AssertReturn((pThis)->cRefs > 0, (rc)); \ 75 76 } while (0) … … 77 78 78 79 /** 79 * Hook function for the thread-preempting event. 80 * 81 * @param pvThreadCtxInt Opaque pointer to the internal thread-context 82 * object. 80 * Hook function for the thread-save event. 81 * 82 * @param pvThreadCtxInt Opaque pointer to the internal hook object. 83 83 * 84 84 * @remarks Called with the with preemption disabled! 85 85 */ 86 static void rtThreadCtxHook sSolPreempting(void *pvThreadCtxInt)87 { 88 PRTTHREADCTX INT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;86 static void rtThreadCtxHookSolOut(void *pvThreadCtxInt) 87 { 88 PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt; 89 89 AssertPtr(pThis); 90 90 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 91 92 if (pThis->fRegistered) 93 { 94 Assert(pThis->pfnThreadCtxHook); 95 pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser); 91 Assert(pThis->cRefs > 0); 92 93 if (pThis->fEnabled) 94 { 95 Assert(pThis->pfnCallback); 96 pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser); 96 97 } 97 98 } … … 99 100 100 101 /** 101 * Hook function for the thread-resumed event. 102 * 103 * @param pvThreadCtxInt Opaque pointer to the internal thread-context 104 * object. 105 */ 106 static void rtThreadCtxHooksSolResumed(void *pvThreadCtxInt) 107 { 108 PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt; 102 * Hook function for the thread-restore event. 103 * 104 * @param pvThreadCtxInt Opaque pointer to the internal hook object. 105 */ 106 static void rtThreadCtxHookSolIn(void *pvThreadCtxInt) 107 { 108 PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt; 109 109 AssertPtr(pThis); 110 110 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 111 112 if (pThis->fRegistered) 113 { 114 Assert(pThis->pfnThreadCtxHook); 115 pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser); 111 Assert(pThis->cRefs > 0); 112 113 if (pThis->fEnabled) 114 { 115 Assert(pThis->pfnCallback); 116 pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser); 116 117 } 117 118 } … … 121 122 * Hook function for the thread-free event. 122 123 * 123 * @param pvThreadCtxInt Opaque pointer to the internal thread-context 124 * object. 124 * This is used for making sure the hook object is safely released - see 125 * RTThreadCtxHookRelease for details. 126 * 127 * @param pvThreadCtxInt Opaque pointer to the internal hook object. 125 128 * @param fIsExec Whether this event is triggered due to exec(). 126 129 */ 127 static void rtThreadCtxHook sSolFree(void *pvThreadCtxInt, int fIsExec)128 { 129 PRTTHREADCTX INT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;130 static void rtThreadCtxHookSolFree(void *pvThreadCtxInt, int fIsExec) 131 { 132 PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt; 130 133 AssertPtrReturnVoid(pThis); 131 AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTX INT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));134 AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis)); 132 135 133 136 uint32_t cRefs = ASMAtomicReadU32(&pThis->cRefs); 134 if (RT_UNLIKELY(!cRefs)) 137 if (cRefs > 0) 138 { 139 cRefs = ASMAtomicDecU32(&pThis->cRefs); 140 if (!cRefs) 141 { 142 Assert(!pThis->fEnabled); 143 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC); 144 RTMemFree(pThis); 145 } 146 } 147 else 135 148 { 136 149 /* Should never happen. */ 137 AssertMsgFailed(("rtThreadCtxHooksSolFree with cRefs=0 pThis=%p\n", pThis)); 138 return; 139 } 140 141 cRefs = ASMAtomicDecU32(&pThis->cRefs); 142 if (!cRefs) 143 { 144 Assert(!pThis->fRegistered); 145 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); 146 RTMemFree(pThis); 147 } 148 } 149 150 151 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx) 152 { 153 PRTTHREADCTXINT pThis; 150 AssertMsgFailed(("rtThreadCtxHookSolFree with cRefs=0 pThis=%p\n", pThis)); 151 } 152 } 153 154 155 RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser) 156 { 157 /* 158 * Validate input. 159 */ 160 PRTTHREADCTXHOOKINT pThis; 154 161 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 155 156 pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis)); 162 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); 163 AssertReturn(fFlags == 0, VERR_INVALID_FLAGS); 164 165 /* 166 * Allocate and initialize a new hook. 167 */ 168 pThis = (PRTTHREADCTXHOOKINT)RTMemAllocZ(sizeof(*pThis)); 157 169 if (RT_UNLIKELY(!pThis)) 158 170 return VERR_NO_MEMORY; 159 pThis->u32Magic = RTTHREADCTXINT_MAGIC; 160 pThis->hOwner = RTThreadNativeSelf(); 161 pThis->fRegistered = false; 162 pThis->cRefs = 2; /* One reference for the thread, one for the hook object. */ 163 164 /* 165 * installctx() allocates memory and thus cannot be used in RTThreadCtxHooksRegister() which can be used 166 * with preemption disabled. We allocate the context-hooks here and use 'fRegistered' to determine if we can 171 pThis->u32Magic = RTTHREADCTXHOOKINT_MAGIC; 172 pThis->hOwner = RTThreadNativeSelf(); 173 pThis->pfnCallback = pfnCallback; 174 pThis->pvUser = pvUser; 175 pThis->fEnabled = false; 176 pThis->cRefs = 2; /* One reference for the thread, one for the caller. */ 177 178 /* 179 * installctx() allocates memory and thus cannot be used in RTThreadCtxHookRegister() which can be used 180 * with preemption disabled. We allocate the context-hooks here and use 'fEnabled' to determine if we can 167 181 * invoke the consumer's hook or not. 168 182 */ … … 171 185 g_rtSolThreadCtx.Install.pfnSol_installctx_old(curthread, 172 186 pThis, 173 rtThreadCtxHook sSolPreempting,174 rtThreadCtxHook sSolResumed,175 NULL, 176 NULL, 177 rtThreadCtxHook sSolFree);187 rtThreadCtxHookSolOut, /* save */ 188 rtThreadCtxHookSolIn, /* restore */ 189 NULL, /* fork */ 190 NULL, /* lwp_create */ 191 rtThreadCtxHookSolFree); 178 192 } 179 193 else … … 181 195 g_rtSolThreadCtx.Install.pfnSol_installctx(curthread, 182 196 pThis, 183 rtThreadCtxHook sSolPreempting,184 rtThreadCtxHook sSolResumed,185 NULL, 186 NULL, 187 NULL, 188 rtThreadCtxHook sSolFree);189 } 190 191 *ph ThreadCtx= pThis;197 rtThreadCtxHookSolOut, /* save */ 198 rtThreadCtxHookSolIn, /* restore */ 199 NULL, /* fork */ 200 NULL, /* lwp_create */ 201 NULL, /* exit */ 202 rtThreadCtxHookSolFree); 203 } 204 205 *phCtxHook = pThis; 192 206 return VINF_SUCCESS; 193 207 } 194 208 195 209 196 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 197 { 198 PRTTHREADCTXINT pThis = hThreadCtx; 199 RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX); 200 201 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 202 Assert(cRefs < UINT32_MAX / 2); 203 return cRefs; 204 } 205 206 207 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 208 { 209 PRTTHREADCTXINT pThis = hThreadCtx; 210 if (pThis == NIL_RTTHREADCTX) 211 return 0; 212 213 RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX); 210 RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook) 211 { 212 /* 213 * Validate input, ignoring NIL. 214 */ 215 PRTTHREADCTXHOOKINT pThis = hCtxHook; 216 if (pThis == NIL_RTTHREADCTXHOOK) 217 return VINF_SUCCESS; 218 RTTHREADCTX_VALID_RETURN_RC(hCtxHook, VERR_INVALID_HANDLE); 214 219 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 215 216 ASMAtomicWriteBool(&pThis->fRegistered, false); 220 Assert(pThis->fEnabled || pThis->hOwner == RTThreadNativeSelf()); 221 222 /* 223 * Make sure it's disabled. 224 */ 225 ASMAtomicWriteBool(&pThis->fEnabled, false); 226 227 /* 228 * Decrement. 229 */ 217 230 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs); 218 219 231 if ( cRefs == 1 220 232 && pThis->hOwner == RTThreadNativeSelf()) 221 233 { 222 234 /* 223 * removectx() will invoke rtThreadCtxHook sSolFree() and there is no way to bypass it and still use224 * rtThreadCtxHook sSolFree() at the same time. Hence the convulated reference counting.235 * removectx() will invoke rtThreadCtxHookSolFree() and there is no way to bypass it and still use 236 * rtThreadCtxHookSolFree() at the same time. Hence the convulated reference counting. 225 237 * 226 238 * When this function is called from the owner thread and is the last reference, we call removectx() which 227 * will invoke rtThreadCtxHook sSolFree() with cRefs = 1 and that will then free the hook object.239 * will invoke rtThreadCtxHookSolFree() with cRefs = 1 and that will then free the hook object. 228 240 * 229 241 * When the function is called from a different thread, we simply decrement the reference. Whenever the 230 * ring-0 thread dies, Solaris will call rtThreadCtxHook sSolFree() which will free the hook object.242 * ring-0 thread dies, Solaris will call rtThreadCtxHookSolFree() which will free the hook object. 231 243 */ 232 244 int rc; … … 235 247 rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread, 236 248 pThis, 237 rtThreadCtxHook sSolPreempting,238 rtThreadCtxHook sSolResumed,239 NULL, 240 NULL, 241 rtThreadCtxHook sSolFree);249 rtThreadCtxHookSolOut, /* save */ 250 rtThreadCtxHookSolIn, /* restore */ 251 NULL, /* fork */ 252 NULL, /* lwp_create */ 253 rtThreadCtxHookSolFree); 242 254 } 243 255 else … … 245 257 rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread, 246 258 pThis, 247 rtThreadCtxHook sSolPreempting,248 rtThreadCtxHook sSolResumed,249 NULL, 250 NULL, 251 NULL, 252 rtThreadCtxHook sSolFree);259 rtThreadCtxHookSolOut, /* save */ 260 rtThreadCtxHookSolIn, /* restore */ 261 NULL, /* fork */ 262 NULL, /* lwp_create */ 263 NULL, /* exit */ 264 rtThreadCtxHookSolFree); 253 265 } 254 266 AssertMsg(rc, ("removectx() failed. rc=%d\n", rc)); … … 267 279 */ 268 280 Assert(pThis->hOwner != RTThreadNativeSelf()); 269 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTX INT_MAGIC);281 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC); 270 282 RTMemFree(pThis); 271 283 } … … 275 287 276 288 277 RTDECL(int) RTThreadCtxHook sRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)289 RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook) 278 290 { 279 291 /* 280 292 * Validate input. 281 293 */ 282 PRTTHREADCTXINT pThis = hThreadCtx; 283 if (pThis == NIL_RTTHREADCTX) 284 return VERR_INVALID_HANDLE; 294 PRTTHREADCTXHOOKINT pThis = hCtxHook; 285 295 AssertPtr(pThis); 286 AssertMsgReturn(pThis->u32Magic == RTTHREADCTX INT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),296 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 287 297 VERR_INVALID_HANDLE); 288 298 Assert(pThis->hOwner == RTThreadNativeSelf()); 289 290 /* 291 * Register the callback. 292 */ 293 pThis->pvUser = pvUser; 294 pThis->pfnThreadCtxHook = pfnThreadCtxHook; 295 pThis->fRegistered = true; 299 Assert(!pThis->fEnabled); 300 301 /* 302 * Mark it as enabled. 303 */ 304 pThis->fEnabled = true; 296 305 297 306 return VINF_SUCCESS; … … 299 308 300 309 301 RTDECL(int) RTThreadCtxHook sDeregister(RTTHREADCTX hThreadCtx)310 RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook) 302 311 { 303 312 /* 304 313 * Validate input. 305 314 */ 306 PRTTHREADCTX INT pThis = hThreadCtx;307 if (pThis == NIL_RTTHREADCTX)308 return VERR_INVALID_HANDLE;309 AssertPtr(pThis);310 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),311 VERR_INVALID_HANDLE);312 Assert(pThis->hOwner == RTThreadNativeSelf());313 Assert(pThis->fRegistered); 314 315 /*316 * Deregister the callback.317 */318 pThis->fRegistered = false;315 PRTTHREADCTXHOOKINT pThis = hCtxHook; 316 if (pThis != NIL_RTTHREADCTXHOOK) 317 { 318 AssertPtr(pThis); 319 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 320 VERR_INVALID_HANDLE); 321 Assert(pThis->hOwner == RTThreadNativeSelf()); 322 323 /* 324 * Mark it as disabled. 325 */ 326 pThis->fEnabled = false; 327 } 319 328 320 329 return VINF_SUCCESS; … … 322 331 323 332 324 RTDECL(bool) RTThreadCtxHook sAreRegistered(RTTHREADCTX hThreadCtx)333 RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook) 325 334 { 326 335 /* 327 336 * Validate input. 328 337 */ 329 PRTTHREADCTX INT pThis = hThreadCtx;330 if (pThis == NIL_RTTHREADCTX )338 PRTTHREADCTXHOOKINT pThis = hCtxHook; 339 if (pThis == NIL_RTTHREADCTXHOOK) 331 340 return false; 332 341 AssertPtr(pThis); 333 AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis)); 334 335 return pThis->fRegistered; 336 } 337 342 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 343 false); 344 345 return pThis->fEnabled; 346 } 347 -
trunk/src/VBox/Runtime/testcase/tstRTR0ThreadPreemption.cpp
r54453 r55863 49 49 RTCPUID uSourceCpuId; 50 50 RTNATIVETHREAD hSourceThread; 51 RTTHREADCTX hThreadCtx;52 51 53 52 /* For RTTHREADCTXEVENT_PREEMPTING. */ … … 82 81 switch (enmEvent) 83 82 { 84 case RTTHREADCTXEVENT_ PREEMPTING:83 case RTTHREADCTXEVENT_OUT: 85 84 { 86 85 ASMAtomicWriteBool(&pData->fPreemptingInvoked, true); … … 119 118 } 120 119 121 case RTTHREADCTXEVENT_ RESUMED:120 case RTTHREADCTXEVENT_IN: 122 121 { 123 122 ASMAtomicWriteBool(&pData->fResumedInvoked, true); … … 302 301 } 303 302 304 bool fRegistered = RTThreadCtxHook sAreRegistered(NIL_RTTHREADCTX);303 bool fRegistered = RTThreadCtxHookIsEnabled(NIL_RTTHREADCTXHOOK); 305 304 if (fRegistered) 306 305 { 307 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered returns true before creating any hooks"); 308 break; 309 } 310 311 RTTHREADCTX hThreadCtx; 312 int rc = RTThreadCtxHooksCreate(&hThreadCtx); 313 if (RT_FAILURE(rc)) 314 { 315 if (rc == VERR_NOT_SUPPORTED) 316 RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED"); 317 else 318 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc); 319 break; 320 } 321 322 fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx); 323 if (fRegistered) 324 { 325 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered returns true before registering any hooks"); 326 RTThreadCtxHooksRelease(hThreadCtx); 306 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled returns true before creating any hooks"); 327 307 break; 328 308 } … … 331 311 AssertReturn(pCtxData, VERR_NO_MEMORY); 332 312 pCtxData->u32Magic = TSTRTR0THREADCTXDATA_MAGIC; 333 pCtxData->hThreadCtx = hThreadCtx;334 313 pCtxData->fPreemptingSuccess = false; 335 314 pCtxData->fPreemptingInvoked = false; … … 339 318 RT_ZERO(pCtxData->achResult); 340 319 320 RTTHREADCTXHOOK hThreadCtx; 321 int rc = RTThreadCtxHookCreate(&hThreadCtx, 0, tstRTR0ThreadCtxHook, pCtxData); 322 if (RT_FAILURE(rc)) 323 { 324 if (rc == VERR_NOT_SUPPORTED) 325 RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED"); 326 else 327 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc); 328 RTMemFree(pCtxData); 329 break; 330 } 331 332 fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx); 333 if (fRegistered) 334 { 335 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled returns true before registering any hooks"); 336 RTThreadCtxHookDestroy(hThreadCtx); 337 break; 338 } 339 341 340 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 342 341 RTThreadPreemptDisable(&PreemptState); … … 345 344 pCtxData->uSourceCpuId = RTMpCpuId(); 346 345 347 rc = RTThreadCtxHook sRegister(hThreadCtx, &tstRTR0ThreadCtxHook, pCtxData);346 rc = RTThreadCtxHookEnable(hThreadCtx); 348 347 if (RT_FAILURE(rc)) 349 348 { 350 349 RTThreadPreemptRestore(&PreemptState); 351 350 RTMemFree(pCtxData); 352 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHook sRegisterreturns %Rrc", rc);353 break; 354 } 355 356 fRegistered = RTThreadCtxHook sAreRegistered(hThreadCtx);351 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookEnable returns %Rrc", rc); 352 break; 353 } 354 355 fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx); 357 356 if (!fRegistered) 358 357 { 359 358 RTThreadPreemptRestore(&PreemptState); 360 359 RTMemFree(pCtxData); 361 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHook sAreRegistered return false when hooks are supposedly registered");360 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return false when hooks are supposedly registered"); 362 361 break; 363 362 } … … 428 427 } 429 428 430 RTThreadCtxHook sDeregister(hThreadCtx);431 432 fRegistered = RTThreadCtxHook sAreRegistered(hThreadCtx);429 RTThreadCtxHookDisable(hThreadCtx); 430 431 fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx); 433 432 if (fRegistered) 434 433 { 435 434 RTMemFree(pCtxData); 436 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHook sAreRegistered return true when hooks are deregistered");435 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return true when hooks are deregistered"); 437 436 break; 438 437 } 439 438 440 439 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 441 uint32_t cRefs = RTThreadCtxHooksRelease(hThreadCtx);442 if ( cRefs == UINT32_MAX)443 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns invalid cRefs!");440 rc = RTThreadCtxHookDestroy(hThreadCtx); 441 if (RT_FAILURE(rc)) 442 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns %Rrc!", rc); 444 443 445 444 RTMemFree(pCtxData);
Note:
See TracChangeset
for help on using the changeset viewer.