- Timestamp:
- May 14, 2015 6:29:34 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/hm.h
r55306 r55863 182 182 VMMR0_INT_DECL(void) HMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, 183 183 unsigned uPort, unsigned uAndVal, unsigned cbSize); 184 #ifdef VBOX_STRICT185 # define HM_DISABLE_PREEMPT() \186 RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \187 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD) || VMMR0ThreadCtxHooksAreRegistered(pVCpu)); \188 RTThreadPreemptDisable(&PreemptStateInternal);189 #else190 # define HM_DISABLE_PREEMPT() \191 RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \192 RTThreadPreemptDisable(&PreemptStateInternal);193 #endif /* VBOX_STRICT */194 # define HM_RESTORE_PREEMPT() do { RTThreadPreemptRestore(&PreemptStateInternal); } while(0)195 196 197 184 VMMR0_INT_DECL(int) HMR0SetupVM(PVM pVM); 198 185 VMMR0_INT_DECL(int) HMR0RunGuestCode(PVM pVM, PVMCPU pVCpu); -
trunk/include/VBox/vmm/vmm.h
r55129 r55863 512 512 VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPU pVCpu); 513 513 VMMR0_INT_DECL(bool) VMMR0IsInRing3LongJump(PVMCPU pVCpu); 514 VMMR0_INT_DECL(int) VMMR0ThreadCtxHooksCreate(PVMCPU pVCpu); 515 VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksRelease(PVMCPU pVCpu); 516 VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreCreated(PVMCPU pVCpu); 517 VMMR0_INT_DECL(int) VMMR0ThreadCtxHooksRegister(PVMCPU pVCpu, PFNRTTHREADCTXHOOK pfnHook); 518 VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksDeregister(PVMCPU pVCpu); 519 VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreRegistered(PVMCPU pVCpu); 514 VMMR0_INT_DECL(int) VMMR0ThreadCtxHookCreateForEmt(PVMCPU pVCpu); 515 VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDestroyForEmt(PVMCPU pVCpu); 516 VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDisable(PVMCPU pVCpu); 517 VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPU pVCpu); 520 518 521 519 # ifdef LOG_ENABLED -
trunk/include/iprt/mangling.h
r55584 r55863 1682 1682 # define RTThreadCreateF RT_MANGLER(RTThreadCreateF) 1683 1683 # define RTThreadCreateV RT_MANGLER(RTThreadCreateV) 1684 # define RTThreadCtxHooksAreRegistered RT_MANGLER(RTThreadCtxHooksAreRegistered) /* r0drv */ 1685 # define RTThreadCtxHooksCreate RT_MANGLER(RTThreadCtxHooksCreate) /* r0drv */ 1686 # define RTThreadCtxHooksDeregister RT_MANGLER(RTThreadCtxHooksDeregister) /* r0drv */ 1687 # define RTThreadCtxHooksRegister RT_MANGLER(RTThreadCtxHooksRegister) /* r0drv */ 1688 # define RTThreadCtxHooksRelease RT_MANGLER(RTThreadCtxHooksRelease) /* r0drv */ 1689 # define RTThreadCtxHooksRetain RT_MANGLER(RTThreadCtxHooksRetain) /* r0drv */ 1684 # define RTThreadCtxHookIsEnabled RT_MANGLER(RTThreadCtxHookIsEnabled) /* r0drv */ 1685 # define RTThreadCtxHookCreate RT_MANGLER(RTThreadCtxHookCreate) /* r0drv */ 1686 # define RTThreadCtxHookDestroy RT_MANGLER(RTThreadCtxHookDestroy) /* r0drv */ 1687 # define RTThreadCtxHookDisable RT_MANGLER(RTThreadCtxHookDisable) /* r0drv */ 1688 # define RTThreadCtxHookEnable RT_MANGLER(RTThreadCtxHookEnable) /* r0drv */ 1690 1689 # define RTThreadFromNative RT_MANGLER(RTThreadFromNative) 1691 1690 # define RTThreadGetAffinity RT_MANGLER(RTThreadGetAffinity) -
trunk/include/iprt/thread.h
r55386 r55863 588 588 589 589 /** 590 * Thread -contextevents.590 * Thread context swithcing events. 591 591 */ 592 592 typedef enum RTTHREADCTXEVENT 593 593 { 594 /** This thread is about to be preempted. */ 595 RTTHREADCTXEVENT_PREEMPTING = 0, 596 /** This thread has just been resumed. */ 597 RTTHREADCTXEVENT_RESUMED, 594 /** This thread is being scheduled out on the current CPU (includes preemption, 595 * waiting, sleep and whatever else may trigger scheduling). */ 596 RTTHREADCTXEVENT_OUT = 0, 597 /** This thread is being scheduled in on the current CPU and will resume 598 * execution. */ 599 RTTHREADCTXEVENT_IN, 598 600 /** The usual 32-bit size hack. */ 599 601 RTTHREADCTXEVENT_32BIT_HACK = 0x7fffffff … … 601 603 602 604 /** 603 * Thread-context hook. 604 * 605 * @returns IPRT status code. 606 * @param enmEvent The thread-context event. 605 * Thread context switching hook callback. 606 * 607 * This hook function is called when a thread is scheduled and preempted. Check 608 * @a enmEvent to see which it is. Since the function is being called from 609 * hooks inside the scheduler, it is limited what you can do from this function. 610 * Do NOT acquire locks, sleep or yield the thread for instance. IRQ safe 611 * spinlocks are fine though. 612 * 613 * @returns IPRT status code. 614 * @param enmEvent The thread-context event. Please quitely ignore unknown 615 * events, we may add more (thread exit, ++) later. 607 616 * @param pvUser User argument. 608 *609 * @remarks This function may be called under different contexts, i.e. with610 * different locks held, with/without preemption disabled depending on611 * the event in @a enmEvent.612 617 */ 613 618 typedef DECLCALLBACK(void) FNRTTHREADCTXHOOK(RTTHREADCTXEVENT enmEvent, void *pvUser); 614 /** Pointer to a thread-contexthook. */619 /** Pointer to a context switching hook. */ 615 620 typedef FNRTTHREADCTXHOOK *PFNRTTHREADCTXHOOK; 616 621 617 622 /** 618 * Initializes a thread-context hook for the current thread. 619 * 620 * This must be called once per-thread before using RTThreadCtxHooksRegister(). 621 * 622 * @returns IPRT status code. 623 * @param phThreadCtx Where to store the thread-context handle. 624 * 625 * @remarks This must be called with preemption enabled! 626 */ 627 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx); 628 629 /** 630 * Retains a new reference to a thread-context hook. 631 * 632 * @returns New reference count. 633 * UINT32_MAX is returned if the handle is invalid (asserted). 634 * @param phThreadCtx Pointer to the thread-context handle. 635 * 636 * @remarks This can be called from any thread. Can be called with preemption 637 * disabled. 638 */ 639 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx); 640 641 /** 642 * Releases a reference to a thread-context hook. 643 * 644 * @returns New reference count. 645 * @retval 0 if the thread-context hook was freed or @a hThreadCtx is 646 * NIL_RTTHREADCTX. 647 * @retval UINT32_MAX is returned if the handle is invalid (asserted). 648 * 649 * @param hThreadCtx The thread-context handle. 650 * 651 * @remarks This can be called from any thread but must be called with 652 * preemption enabled! 653 */ 654 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx); 655 656 /** 657 * Registers a thread-context hook for the current thread to receive 658 * notifications for all supported thread-context events. 659 * 660 * @returns IPRT status code. 661 * @param hThreadCtx The thread-context handle. 662 * @param pfnThreadHook Pointer to a thread-context hook (a callback) 663 * for all thread-context events. 664 * @param pvUser User argument (optional, can be NULL). 665 * 666 * @remarks Can be called with preemption disabled. 667 */ 668 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadHook, void *pvUser); 669 670 /** 671 * Deregisters the thread-context hook for the current thread. 672 * 673 * @returns IPRT status code. 674 * @param hThreadCtx The thread-context handle. 675 * 676 * @remarks Can be called with preemption disabled. 677 */ 678 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx); 679 680 /** 681 * Are thread-context hooks registered for the thread? 623 * Initializes a thread context switching hook for the current thread. 624 * 625 * The hook is created as disabled, use RTThreadCtxHookEnable to enable it. 626 * 627 * @returns IPRT status code. 628 * @param phCtxHook Where to store the hook handle. 629 * @param fFlags Reserved for future extensions, must be zero. 630 * @param pfnCallback Pointer to a the hook function (callback) that 631 * should be called for all context switching events 632 * involving the current thread. 633 * @param pvUser User argument that will be passed to @a pfnCallback. 634 * @remarks Preemption must be enabled. 635 */ 636 RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser); 637 638 /** 639 * Destroys a thread context switching hook. 640 * 641 * Caller must make sure the hook is disabled before the final reference is 642 * released. Recommended to call this on the owning thread, otherwise the 643 * memory backing it may on some systems only be released when the thread 644 * terminates. 645 * 646 * @returns IPRT status code. 647 * 648 * @param hCtxHook The context hook handle. NIL_RTTHREADCTXHOOK is 649 * ignored and the function will return VINF_SUCCESS. 650 * @remarks Preemption must be enabled. 651 * @remarks Do not call from FNRTTHREADCTXHOOK. 652 */ 653 RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook); 654 655 /** 656 * Enables the context switching hooks for the current thread. 657 * 658 * @returns IPRT status code. 659 * @param hCtxHook The context hook handle. 660 * @remarks Should be called with preemption disabled. 661 */ 662 RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook); 663 664 /** 665 * Disables the thread context switching hook for the current thread. 666 * 667 * Will not assert or fail if called twice or with a NIL handle. 668 * 669 * @returns IPRT status code. 670 * @param hCtxHook The context hook handle. NIL_RTTHREADCTXHOOK is 671 * ignored and the function wil return VINF_SUCCESS. 672 * @remarks Should be called with preemption disabled. 673 * @remarks Do not call from FNRTTHREADCTXHOOK. 674 */ 675 RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook); 676 677 /** 678 * Is the thread context switching hook enabled? 682 679 * 683 680 * @returns true if registered, false if not supported or not registered. 684 * @param hThreadCtx The thread-context handle. 685 * 686 * @remarks Can be called from any thread (but possibility of races when 687 * it's not the current thread!) 688 */ 689 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx); 681 * @param hCtxHook The context hook handle. NIL_RTTHREADCTXHOOK is 682 * ignored and the function will return false. 683 * 684 * @remarks Can be called from any thread, though is naturally subject to races 685 * when not called from the thread associated with the hook. 686 */ 687 RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook); 690 688 691 689 # endif /* IN_RING0 */ -
trunk/include/iprt/types.h
r53615 r55863 1763 1763 #define NIL_RTTHREAD 0 1764 1764 1765 /** Thread -context handle.*/1766 typedef R0PTRTYPE(struct RTTHREADCTX INT *) RTTHREADCTX;1767 /** Pointer to threadhandle. */1768 typedef RTTHREADCTX *PRTTHREADCTX;1769 /** Nil thread-contexthandle. */1770 #define NIL_RTTHREADCTX 01765 /** Thread context switching hook handle. */ 1766 typedef R0PTRTYPE(struct RTTHREADCTXHOOKINT *) RTTHREADCTXHOOK; 1767 /** Pointer to Thread context switching hook handle. */ 1768 typedef RTTHREADCTXHOOK *PRTTHREADCTXHOOK; 1769 /** Nil Thread context switching hook handle. */ 1770 #define NIL_RTTHREADCTXHOOK ((RTTHREADCTXHOOK)0) 1771 1771 1772 1772 /** A TLS index. */ -
trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
r55436 r55863 360 360 { "RTStrPrintfV", (void *)RTStrPrintfV }, 361 361 { "RTThreadCreate", (void *)RTThreadCreate }, 362 { "RTThreadCtxHooksAreRegistered", (void *)RTThreadCtxHooksAreRegistered }, 363 { "RTThreadCtxHooksCreate", (void *)RTThreadCtxHooksCreate }, 364 { "RTThreadCtxHooksDeregister", (void *)RTThreadCtxHooksDeregister }, 365 { "RTThreadCtxHooksRegister", (void *)RTThreadCtxHooksRegister }, 366 { "RTThreadCtxHooksRelease", (void *)RTThreadCtxHooksRelease }, 367 { "RTThreadCtxHooksRetain", (void *)RTThreadCtxHooksRetain }, 362 { "RTThreadCtxHookIsEnabled", (void *)RTThreadCtxHookIsEnabled }, 363 { "RTThreadCtxHookCreate", (void *)RTThreadCtxHookCreate }, 364 { "RTThreadCtxHookDestroy", (void *)RTThreadCtxHookDestroy }, 365 { "RTThreadCtxHookDisable", (void *)RTThreadCtxHookDisable }, 366 { "RTThreadCtxHookEnable", (void *)RTThreadCtxHookEnable }, 368 367 { "RTThreadGetName", (void *)RTThreadGetName }, 369 368 { "RTThreadGetNative", (void *)RTThreadGetNative }, -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r55436 r55863 215 215 * - (nothing) 216 216 */ 217 #define SUPDRV_IOC_VERSION 0x002 00000217 #define SUPDRV_IOC_VERSION 0x00220000 218 218 219 219 /** SUP_IOCTL_COOKIE. */ -
trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
r54446 r55863 194 194 ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \ 195 195 ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c=>r0drv/generic/semspinmutex-r0drv-generic.c \ 196 ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp=>r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 196 197 ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \ 197 198 ${PATH_ROOT}/src/VBox/Runtime/VBox/log-vbox.cpp=>VBox/log-vbox.c \ -
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); -
trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
r54191 r55863 889 889 pGVMM->cEMTs += cCpus; 890 890 891 rc = VMMR0ThreadCtxHook sCreate(&pVM->aCpus[0]);891 rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[0]); 892 892 if (RT_SUCCESS(rc)) 893 893 { … … 1123 1123 * solution for not deregistering hooks everytime we're leaving HMR0 1124 1124 * context. */ 1125 VMMR0ThreadCtxHook sRelease(&pVM->aCpus[idCpu]);1125 VMMR0ThreadCtxHookDestroyForEmt(&pVM->aCpus[idCpu]); 1126 1126 } 1127 1127 … … 1351 1351 pVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf(); 1352 1352 1353 rc = VMMR0ThreadCtxHooksCreate(&pVM->aCpus[idCpu]); 1354 return rc; 1353 return VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[idCpu]); 1355 1354 } 1356 1355 -
trunk/src/VBox/VMM/VMMR0/HMR0.cpp
r55755 r55863 1366 1366 1367 1367 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE 1368 AssertReturn(!VMMR0ThreadCtxHook sAreRegistered(pVCpu), VERR_HM_IPE_5);1368 AssertReturn(!VMMR0ThreadCtxHookIsEnabled(pVCpu), VERR_HM_IPE_5); 1369 1369 bool fStartedSet = PGMR0DynMapStartOrMigrateAutoSet(pVCpu); 1370 1370 #endif … … 1471 1471 1472 1472 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE 1473 AssertReturn(!VMMR0ThreadCtxHook sAreRegistered(pVCpu), VERR_HM_IPE_4);1473 AssertReturn(!VMMR0ThreadCtxHookIsEnabled(pVCpu), VERR_HM_IPE_4); 1474 1474 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 1475 1475 PGMRZDynMapStartAutoSet(pVCpu); -
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r55830 r55863 121 121 122 122 /** Assert that preemption is disabled or covered by thread-context hooks. */ 123 #define HMSVM_ASSERT_PREEMPT_SAFE() Assert( VMMR0ThreadCtxHook sAreRegistered(pVCpu) \123 #define HMSVM_ASSERT_PREEMPT_SAFE() Assert( VMMR0ThreadCtxHookIsEnabled(pVCpu) \ 124 124 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 125 125 126 126 /** Assert that we haven't migrated CPUs when thread-context hooks are not 127 127 * used. */ 128 #define HMSVM_ASSERT_CPU_SAFE() AssertMsg( VMMR0ThreadCtxHook sAreRegistered(pVCpu) \128 #define HMSVM_ASSERT_CPU_SAFE() AssertMsg( VMMR0ThreadCtxHookIsEnabled(pVCpu) \ 129 129 || pVCpu->hm.s.idEnteredCpu == RTMpCpuId(), \ 130 130 ("Illegal migration! Entered on CPU %u Current %u\n", \ … … 1741 1741 switch (enmEvent) 1742 1742 { 1743 case RTTHREADCTXEVENT_ PREEMPTING:1743 case RTTHREADCTXEVENT_OUT: 1744 1744 { 1745 1745 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 1746 Assert(VMMR0ThreadCtxHook sAreRegistered(pVCpu));1746 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu)); 1747 1747 VMCPU_ASSERT_EMT(pVCpu); 1748 1748 … … 1769 1769 } 1770 1770 1771 case RTTHREADCTXEVENT_ RESUMED:1771 case RTTHREADCTXEVENT_IN: 1772 1772 { 1773 1773 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 1774 Assert(VMMR0ThreadCtxHook sAreRegistered(pVCpu));1774 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu)); 1775 1775 VMCPU_ASSERT_EMT(pVCpu); 1776 1776 … … 2140 2140 */ 2141 2141 2142 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */ 2142 2143 /* Deregister hook now that we've left HM context before re-enabling preemption. */ 2143 VMMR0ThreadCtxHook sDeregister(pVCpu);2144 VMMR0ThreadCtxHookDisable(pVCpu); 2144 2145 2145 2146 /* Leave HM context. This takes care of local init (term). */ … … 2198 2199 2199 2200 /* Deregister the hook now that we've left HM context before re-enabling preemption. */ 2200 VMMR0ThreadCtxHooksDeregister(pVCpu); 2201 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */ 2202 VMMR0ThreadCtxHookDisable(pVCpu); 2201 2203 2202 2204 /* Leave HM context. This takes care of local init (term). */ -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r55830 r55863 184 184 185 185 /** Assert that preemption is disabled or covered by thread-context hooks. */ 186 #define HMVMX_ASSERT_PREEMPT_SAFE() Assert( VMMR0ThreadCtxHook sAreRegistered(pVCpu) \186 #define HMVMX_ASSERT_PREEMPT_SAFE() Assert( VMMR0ThreadCtxHookIsEnabled(pVCpu) \ 187 187 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 188 188 189 189 /** Assert that we haven't migrated CPUs when thread-context hooks are not 190 190 * used. */ 191 #define HMVMX_ASSERT_CPU_SAFE() AssertMsg( VMMR0ThreadCtxHook sAreRegistered(pVCpu) \191 #define HMVMX_ASSERT_CPU_SAFE() AssertMsg( VMMR0ThreadCtxHookIsEnabled(pVCpu) \ 192 192 || pVCpu->hm.s.idEnteredCpu == RTMpCpuId(), \ 193 193 ("Illegal migration! Entered on CPU %u Current %u\n", \ … … 7243 7243 /** @todo Deregistering here means we need to VMCLEAR always 7244 7244 * (longjmp/exit-to-r3) in VT-x which is not efficient. */ 7245 VMMR0ThreadCtxHooksDeregister(pVCpu); 7245 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */ 7246 VMMR0ThreadCtxHookDisable(pVCpu); 7246 7247 7247 7248 /* Leave HM context. This takes care of local init (term). */ … … 7376 7377 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions. 7377 7378 */ 7378 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; \7379 7379 VMMRZCallRing3RemoveNotification(pVCpu); 7380 7380 VMMRZCallRing3Disable(pVCpu); 7381 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 7381 7382 RTThreadPreemptDisable(&PreemptState); 7382 7383 … … 7408 7409 } 7409 7410 7410 VMMR0ThreadCtxHooksDeregister(pVCpu); 7411 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */ 7412 VMMR0ThreadCtxHookDisable(pVCpu); 7411 7413 HMR0LeaveCpu(pVCpu); 7412 7414 RTThreadPreemptRestore(&PreemptState); … … 8222 8224 switch (enmEvent) 8223 8225 { 8224 case RTTHREADCTXEVENT_ PREEMPTING:8226 case RTTHREADCTXEVENT_OUT: 8225 8227 { 8226 8228 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 8227 Assert(VMMR0ThreadCtxHook sAreRegistered(pVCpu));8229 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu)); 8228 8230 VMCPU_ASSERT_EMT(pVCpu); 8229 8231 … … 8256 8258 } 8257 8259 8258 case RTTHREADCTXEVENT_ RESUMED:8260 case RTTHREADCTXEVENT_IN: 8259 8261 { 8260 8262 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 8261 Assert(VMMR0ThreadCtxHook sAreRegistered(pVCpu));8263 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu)); 8262 8264 VMCPU_ASSERT_EMT(pVCpu); 8263 8265 … … 10060 10062 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt); 10061 10063 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */ 10062 if (VMMR0ThreadCtxHook sAreRegistered(pVCpu))10064 if (VMMR0ThreadCtxHookIsEnabled(pVCpu)) 10063 10065 return VINF_SUCCESS; 10064 10066 return VINF_EM_RAW_INTERRUPT; -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r55715 r55863 447 447 448 448 /** 449 * Creates R0 thread-context hooks for the current EMT thread.450 *451 * @returns VBox status code.452 * @param pVCpu Pointer to the VMCPU.453 *454 * @thread EMT(pVCpu)455 */456 VMMR0_INT_DECL(int) VMMR0ThreadCtxHooksCreate(PVMCPU pVCpu)457 {458 VMCPU_ASSERT_EMT(pVCpu);459 Assert(pVCpu->vmm.s.hR0ThreadCtx == NIL_RTTHREADCTX);460 #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)461 int rc = RTThreadCtxHooksCreate(&pVCpu->vmm.s.hR0ThreadCtx);462 if ( RT_FAILURE(rc)463 && rc != VERR_NOT_SUPPORTED)464 {465 Log(("RTThreadCtxHooksCreate failed! rc=%Rrc pVCpu=%p idCpu=%RU32\n", rc, pVCpu, pVCpu->idCpu));466 return rc;467 }468 #endif469 470 return VINF_SUCCESS;471 }472 473 474 /**475 * Releases the object reference for the thread-context hook.476 *477 * @param pVCpu Pointer to the VMCPU.478 * @remarks Can be called from any thread.479 */480 VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksRelease(PVMCPU pVCpu)481 {482 RTThreadCtxHooksRelease(pVCpu->vmm.s.hR0ThreadCtx);483 }484 485 486 /**487 * Registers the thread-context hook for this VCPU.488 *489 * @returns VBox status code.490 * @param pVCpu Pointer to the VMCPU.491 * @param pfnThreadHook Pointer to the thread-context callback.492 *493 * @thread EMT(pVCpu)494 */495 VMMR0_INT_DECL(int) VMMR0ThreadCtxHooksRegister(PVMCPU pVCpu, PFNRTTHREADCTXHOOK pfnThreadHook)496 {497 VMCPU_ASSERT_EMT(pVCpu);498 return RTThreadCtxHooksRegister(pVCpu->vmm.s.hR0ThreadCtx, pfnThreadHook, pVCpu);499 }500 501 502 /**503 * Deregisters the thread-context hook for this VCPU.504 *505 * @param pVCpu Pointer to the VMCPU.506 *507 * @thread EMT(pVCpu)508 */509 VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksDeregister(PVMCPU pVCpu)510 {511 /* Clear the VCPU <-> host CPU mapping as we've left HM context. See @bugref{7726} comment #19. */512 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);513 514 if (pVCpu->vmm.s.hR0ThreadCtx != NIL_RTTHREADCTX)515 {516 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));517 int rc = RTThreadCtxHooksDeregister(pVCpu->vmm.s.hR0ThreadCtx);518 AssertRC(rc);519 }520 }521 522 523 /**524 * Whether thread-context hooks are created (implying they're supported) on this525 * platform.526 *527 * @returns true if the hooks are created, false otherwise.528 * @param pVCpu Pointer to the VMCPU.529 */530 VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreCreated(PVMCPU pVCpu)531 {532 return pVCpu->vmm.s.hR0ThreadCtx != NIL_RTTHREADCTX;533 }534 535 536 /**537 * Whether thread-context hooks are registered for this VCPU.538 *539 * @returns true if registered, false otherwise.540 * @param pVCpu Pointer to the VMCPU.541 */542 VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreRegistered(PVMCPU pVCpu)543 {544 return RTThreadCtxHooksAreRegistered(pVCpu->vmm.s.hR0ThreadCtx);545 }546 547 548 /**549 449 * VMM ring-0 thread-context callback. 550 450 * … … 563 463 switch (enmEvent) 564 464 { 565 case RTTHREADCTXEVENT_ RESUMED:465 case RTTHREADCTXEVENT_IN: 566 466 { 567 467 /* … … 571 471 * ad infinitum). Let's just disable preemption for now... 572 472 */ 573 HM_DISABLE_PREEMPT(); 473 /** @todo r=bird: I don't believe the above. The linux code is clearly enabling 474 * preemption after doing the callout (one or two functions up the 475 * call chain). */ 476 RTTHREADPREEMPTSTATE ParanoidPreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 477 RTThreadPreemptDisable(&ParanoidPreemptState); 574 478 575 479 /* We need to update the VCPU <-> host CPU mapping. */ … … 589 493 590 494 /* Restore preemption. */ 591 HM_RESTORE_PREEMPT();495 RTThreadPreemptRestore(&ParanoidPreemptState); 592 496 break; 593 497 } 594 498 595 case RTTHREADCTXEVENT_ PREEMPTING:499 case RTTHREADCTXEVENT_OUT: 596 500 { 597 501 /* Invoke the HM-specific thread-context callback. */ … … 612 516 break; 613 517 } 518 } 519 520 521 /** 522 * Creates thread switching hook for the current EMT thread. 523 * 524 * This is called by GVMMR0CreateVM and GVMMR0RegisterVCpu. If the host 525 * platform does not implement switcher hooks, no hooks will be create and the 526 * member set to NIL_RTTHREADCTXHOOK. 527 * 528 * @returns VBox status code. 529 * @param pVCpu Pointer to the cross context CPU structure. 530 * @thread EMT(pVCpu) 531 */ 532 VMMR0_INT_DECL(int) VMMR0ThreadCtxHookCreateForEmt(PVMCPU pVCpu) 533 { 534 VMCPU_ASSERT_EMT(pVCpu); 535 Assert(pVCpu->vmm.s.hCtxHook == NIL_RTTHREADCTXHOOK); 536 537 int rc = RTThreadCtxHookCreate(&pVCpu->vmm.s.hCtxHook, 0, vmmR0ThreadCtxCallback, pVCpu); 538 if (RT_SUCCESS(rc)) 539 return rc; 540 541 pVCpu->vmm.s.hCtxHook = NIL_RTTHREADCTXHOOK; 542 if (rc == VERR_NOT_SUPPORTED) 543 return VINF_SUCCESS; 544 545 LogRelMax(32, ("RTThreadCtxHookCreate failed! rc=%Rrc pVCpu=%p idCpu=%RU32\n", rc, pVCpu, pVCpu->idCpu)); 546 return VINF_SUCCESS; /* Just ignore it, we can live without context hooks. */ 547 } 548 549 550 /** 551 * Destroys the thread switching hook for the specified VCPU. 552 * 553 * @param pVCpu Pointer to the cross context CPU structure. 554 * @remarks Can be called from any thread. 555 */ 556 VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDestroyForEmt(PVMCPU pVCpu) 557 { 558 int rc = RTThreadCtxHookDestroy(pVCpu->vmm.s.hCtxHook); 559 AssertRC(rc); 560 } 561 562 563 /** 564 * Disables the thread switching hook for this VCPU (if we got one). 565 * 566 * @param pVCpu Pointer to the cross context CPU structure. 567 * @thread EMT(pVCpu) 568 * 569 * @remarks This also clears VMCPU::idHostCpu, so the mapping is invalid after 570 * this call. This means you have to be careful with what you do! 571 */ 572 VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDisable(PVMCPU pVCpu) 573 { 574 /* 575 * Clear the VCPU <-> host CPU mapping as we've left HM context. 576 * @bugref{7726} comment #19 explains the need for this trick: 577 * 578 * hmR0VmxCallRing3Callback/hmR0SvmCallRing3Callback & 579 * hmR0VmxLeaveSession/hmR0SvmLeaveSession disables context hooks during 580 * longjmp & normal return to ring-3, which opens a window where we may be 581 * rescheduled without changing VMCPUID::idHostCpu and cause confusion if 582 * the CPU starts executing a different EMT. Both functions first disables 583 * preemption and then calls HMR0LeaveCpu which invalids idHostCpu, leaving 584 * an opening for getting preempted. 585 */ 586 /** @todo Make HM not need this API! Then we could leave the hooks enabled 587 * all the time. */ 588 /** @todo move this into the context hook disabling if(). */ 589 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID); 590 591 /* 592 * Disable the context hook, if we got one. 593 */ 594 if (pVCpu->vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK) 595 { 596 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 597 int rc = RTThreadCtxHookDisable(pVCpu->vmm.s.hCtxHook); 598 AssertRC(rc); 599 } 600 } 601 602 603 /** 604 * Internal version of VMMR0ThreadCtxHooksAreRegistered. 605 * 606 * @returns true if registered, false otherwise. 607 * @param pVCpu Pointer to the VMCPU. 608 */ 609 DECLINLINE(bool) vmmR0ThreadCtxHookIsEnabled(PVMCPU pVCpu) 610 { 611 return RTThreadCtxHookIsEnabled(pVCpu->vmm.s.hCtxHook); 612 } 613 614 615 /** 616 * Whether thread-context hooks are registered for this VCPU. 617 * 618 * @returns true if registered, false otherwise. 619 * @param pVCpu Pointer to the VMCPU. 620 */ 621 VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPU pVCpu) 622 { 623 return vmmR0ThreadCtxHookIsEnabled(pVCpu); 614 624 } 615 625 … … 993 1003 * Disable preemption. 994 1004 */ 995 Assert(! VMMR0ThreadCtxHooksAreRegistered(pVCpu));1005 Assert(!vmmR0ThreadCtxHookIsEnabled(pVCpu)); 996 1006 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 997 1007 RTThreadPreemptDisable(&PreemptState); … … 1038 1048 * Register thread-context hooks if required. 1039 1049 */ 1040 if ( VMMR0ThreadCtxHooksAreCreated(pVCpu)1041 && ! VMMR0ThreadCtxHooksAreRegistered(pVCpu))1050 if ( pVCpu->vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK 1051 && !RTThreadCtxHookIsEnabled(pVCpu->vmm.s.hCtxHook)) 1042 1052 { 1043 rc = VMMR0ThreadCtxHooksRegister(pVCpu, vmmR0ThreadCtxCallback);1053 rc = RTThreadCtxHookEnable(pVCpu->vmm.s.hCtxHook); 1044 1054 AssertRC(rc); 1045 1055 } … … 1057 1067 * we're in HM context. 1058 1068 */ 1059 if ( VMMR0ThreadCtxHooksAreRegistered(pVCpu))1069 if (vmmR0ThreadCtxHookIsEnabled(pVCpu)) 1060 1070 { 1061 1071 fPreemptRestored = true; … … 1080 1090 rc = VERR_VMM_WRONG_HM_VMCPU_STATE; 1081 1091 } 1082 else if (RT_UNLIKELY( VMMR0ThreadCtxHooksAreRegistered(pVCpu)))1092 else if (RT_UNLIKELY(vmmR0ThreadCtxHookIsEnabled(pVCpu))) 1083 1093 { 1084 1094 pVM->vmm.s.szRing0AssertMsg1[0] = '\0'; … … 1091 1101 } 1092 1102 STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC); 1103 1104 /** @todo shouldn't we disable the ctx hook here??? */ 1093 1105 } 1094 1106 /* -
trunk/src/VBox/VMM/VMMR3/VMM.cpp
r55568 r55863 541 541 542 542 /* Log whether thread-context hooks are used (on Linux this can depend on how the kernel is configured). */ 543 if (pVM->aCpus[0].vmm.s.h R0ThreadCtx != NIL_RTTHREADCTX)543 if (pVM->aCpus[0].vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK) 544 544 LogRel(("VMM: Thread-context hooks enabled!\n")); 545 545 else -
trunk/src/VBox/VMM/include/HMInternal.h
r55756 r55863 221 221 #define HM_VTX_TOTAL_DEVHEAP_MEM (HM_EPT_IDENTITY_PG_TABLE_SIZE + HM_VTX_TSS_SIZE) 222 222 223 224 /** @name Macros for enabling and disabling preemption. 225 * These are really just for hiding the RTTHREADPREEMPTSTATE and asserting that 226 * preemption has already been disabled when there is no context hook. 227 * @{ */ 228 #ifdef VBOX_STRICT 229 # define HM_DISABLE_PREEMPT() \ 230 RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \ 231 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD) || VMMR0ThreadCtxHookIsEnabled(pVCpu)); \ 232 RTThreadPreemptDisable(&PreemptStateInternal) 233 #else 234 # define HM_DISABLE_PREEMPT() \ 235 RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \ 236 RTThreadPreemptDisable(&PreemptStateInternal) 237 #endif /* VBOX_STRICT */ 238 #define HM_RESTORE_PREEMPT() do { RTThreadPreemptRestore(&PreemptStateInternal); } while(0) 239 /** @} */ 240 241 223 242 /** Enable for TPR guest patching. */ 224 243 #define VBOX_HM_WITH_GUEST_PATCHING 225 244 226 /** HM SSM version 245 /** @name HM saved state versions 246 * @{ 227 247 */ 228 248 #ifdef VBOX_HM_WITH_GUEST_PATCHING … … 234 254 #endif 235 255 #define HM_SAVED_STATE_VERSION_2_0_X 3 256 /** @} */ 236 257 237 258 /** -
trunk/src/VBox/VMM/include/VMMInternal.h
r53466 r55863 420 420 R0PTRTYPE(PVMMR0LOGGER) pR0LoggerR0; 421 421 422 /** @name Thread-context hooks. 423 * @{*/ 424 R0PTRTYPE(RTTHREADCTX) hR0ThreadCtx; 425 #if HC_ARCH_BITS == 32 426 uint32_t u32Padding; 427 #else 428 uint64_t u64Padding; 429 #endif 430 /** @} */ 422 /** Thread context switching hook (ring-0). */ 423 RTTHREADCTXHOOK hCtxHook; 431 424 432 425 /** @name Rendezvous … … 435 428 * attempts at recursive rendezvous. */ 436 429 bool volatile fInRendezvous; 437 bool afPadding[HC_ARCH_BITS == 32 ? 3 : 7];430 bool afPadding[HC_ARCH_BITS == 32 ? 3+4 : 7+8]; 438 431 /** @} */ 439 432 440 /** @name Raw-mode context trac ting data.433 /** @name Raw-mode context tracing data. 441 434 * @{ */ 442 435 SUPDRVTRACERUSRCTX TracerCtx; -
trunk/src/VBox/VMM/include/VMMInternal.mac
r48499 r55863 108 108 .pR0LoggerR0 RTR0PTR_RES 1 109 109 110 .hR0ThreadCtx RTR0PTR_RES 1 111 %if HC_ARCH_BITS == 32 112 .u32Padding resd 1 113 %else 114 .u64Padding resq 1 115 %endif 110 .hCtxHook RTR0PTR_RES 1 116 111 117 112 .fInRendezvous resb 1 118 113 %if HC_ARCH_BITS == 32 119 .afPadding resb 3 114 .afPadding resb 3+4 120 115 %else 121 .afPadding resb 7 116 .afPadding resb 7+8 122 117 %endif 123 118
Note:
See TracChangeset
for help on using the changeset viewer.