VirtualBox

Changeset 55863 in vbox for trunk


Ignore:
Timestamp:
May 14, 2015 6:29:34 PM (10 years ago)
Author:
vboxsync
Message:

IPRT,SUPDrv,VMM: Revised the context switching hook interface. Do less work when enabling the hook (formerly 'registration'). Drop the reference counting (kept internally for solaris) as it complicates restrictions wrt destroying enabled hooks. Bumped support driver version.

Location:
trunk
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/hm.h

    r55306 r55863  
    182182VMMR0_INT_DECL(void)            HMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext,
    183183                                                          unsigned uPort, unsigned uAndVal, unsigned cbSize);
    184 #ifdef VBOX_STRICT
    185 # define HM_DISABLE_PREEMPT() \
    186     RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \
    187     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD) || VMMR0ThreadCtxHooksAreRegistered(pVCpu)); \
    188     RTThreadPreemptDisable(&PreemptStateInternal);
    189 #else
    190 # 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 
    197184VMMR0_INT_DECL(int)             HMR0SetupVM(PVM pVM);
    198185VMMR0_INT_DECL(int)             HMR0RunGuestCode(PVM pVM, PVMCPU pVCpu);
  • trunk/include/VBox/vmm/vmm.h

    r55129 r55863  
    512512VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPU pVCpu);
    513513VMMR0_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);
     514VMMR0_INT_DECL(int)  VMMR0ThreadCtxHookCreateForEmt(PVMCPU pVCpu);
     515VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDestroyForEmt(PVMCPU pVCpu);
     516VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDisable(PVMCPU pVCpu);
     517VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPU pVCpu);
    520518
    521519# ifdef LOG_ENABLED
  • trunk/include/iprt/mangling.h

    r55584 r55863  
    16821682# define RTThreadCreateF                                RT_MANGLER(RTThreadCreateF)
    16831683# 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 */
    16901689# define RTThreadFromNative                             RT_MANGLER(RTThreadFromNative)
    16911690# define RTThreadGetAffinity                            RT_MANGLER(RTThreadGetAffinity)
  • trunk/include/iprt/thread.h

    r55386 r55863  
    588588
    589589/**
    590  * Thread-context events.
     590 * Thread context swithcing events.
    591591 */
    592592typedef enum RTTHREADCTXEVENT
    593593{
    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,
    598600    /** The usual 32-bit size hack. */
    599601    RTTHREADCTXEVENT_32BIT_HACK = 0x7fffffff
     
    601603
    602604/**
    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.
    607616 * @param   pvUser      User argument.
    608  *
    609  * @remarks This function may be called under different contexts, i.e. with
    610  *          different locks held, with/without preemption disabled depending on
    611  *          the event in @a enmEvent.
    612617 */
    613618typedef DECLCALLBACK(void) FNRTTHREADCTXHOOK(RTTHREADCTXEVENT enmEvent, void *pvUser);
    614 /** Pointer to a thread-context hook. */
     619/** Pointer to a context switching hook. */
    615620typedef FNRTTHREADCTXHOOK *PFNRTTHREADCTXHOOK;
    616621
    617622/**
    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 */
     636RTDECL(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 */
     653RTDECL(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 */
     662RTDECL(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 */
     675RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook);
     676
     677/**
     678 * Is the thread context switching hook enabled?
    682679 *
    683680 * @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 */
     687RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook);
    690688
    691689# endif /* IN_RING0 */
  • trunk/include/iprt/types.h

    r53615 r55863  
    17631763#define NIL_RTTHREAD                                0
    17641764
    1765 /** Thread-context handle.*/
    1766 typedef R0PTRTYPE(struct RTTHREADCTXINT *)          RTTHREADCTX;
    1767 /** Pointer to thread handle. */
    1768 typedef RTTHREADCTX                                *PRTTHREADCTX;
    1769 /** Nil thread-context handle. */
    1770 #define NIL_RTTHREADCTX                             0
     1765/** Thread context switching hook handle.   */
     1766typedef R0PTRTYPE(struct RTTHREADCTXHOOKINT *)      RTTHREADCTXHOOK;
     1767/** Pointer to Thread context switching hook handle. */
     1768typedef RTTHREADCTXHOOK                            *PRTTHREADCTXHOOK;
     1769/** Nil Thread context switching hook handle. */
     1770#define NIL_RTTHREADCTXHOOK                         ((RTTHREADCTXHOOK)0)
    17711771
    17721772/** A TLS index. */
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp

    r55436 r55863  
    360360    { "RTStrPrintfV",                           (void *)RTStrPrintfV },
    361361    { "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 },
    368367    { "RTThreadGetName",                        (void *)RTThreadGetName },
    369368    { "RTThreadGetNative",                      (void *)RTThreadGetNative },
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r55436 r55863  
    215215 *          - (nothing)
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x00200000
     217#define SUPDRV_IOC_VERSION                              0x00220000
    218218
    219219/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv

    r54446 r55863  
    194194    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \
    195195    ${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 \
    196197    ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \
    197198    ${PATH_ROOT}/src/VBox/Runtime/VBox/log-vbox.cpp=>VBox/log-vbox.c \
  • trunk/src/VBox/Runtime/include/internal/magics.h

    r51571 r55863  
    193193/** RTTESTINT::u32Magic value. (Daniel Kehlmann) */
    194194#define RTTESTINT_MAGIC                 UINT32_C(0x19750113)
    195 /** RTTHREADCTXINT::u32Magic value. (Dennis MacAlistair Ritchie) */
    196 #define RTTHREADCTXINT_MAGIC            UINT32_C(0x19410909)
     195/** RTTHREADCTXHOOKINT::u32Magic value. (Dennis MacAlistair Ritchie) */
     196#define RTTHREADCTXHOOKINT_MAGIC        UINT32_C(0x19410909)
    197197/** RTTHREADINT::u32Magic value. (Gilbert Keith Chesterton) */
    198198#define RTTHREADINT_MAGIC               UINT32_C(0x18740529)
  • trunk/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp

    r47572 r55863  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Thread-Context Hooks, Ring-0 Driver, Generic.
     3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Generic.
    44 */
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3434#include "internal/iprt.h"
    3535
    36 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
     36RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
    3737{
    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);
    6339    NOREF(pfnCallback);
    6440    NOREF(pvUser);
    6541    return VERR_NOT_SUPPORTED;
    6642}
    67 RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
     43RT_EXPORT_SYMBOL(RTThreadCtxHookCreate);
    6844
    6945
    70 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
     46RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook)
    7147{
    72     NOREF(hThreadCtx);
     48    return hCtxHook == NIL_RTTHREADCTXHOOK ? VINF_SUCCESS : VERR_INVALID_HANDLE;
     49}
     50RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy);
     51
     52
     53RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
     54{
     55    NOREF(hCtxHook);
    7356    return VERR_NOT_SUPPORTED;
    7457}
    75 RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
     58RT_EXPORT_SYMBOL(RTThreadCtxHookEnable);
    7659
    7760
    78 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
     61RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
    7962{
    80     NOREF(hThreadCtx);
     63    NOREF(hCtxHook);
     64    return VERR_NOT_SUPPORTED;
     65}
     66RT_EXPORT_SYMBOL(RTThreadCtxHookDisable);
     67
     68
     69RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
     70{
     71    NOREF(hCtxHook);
    8172    return false;
    8273}
    83 RT_EXPORT_SYMBOL(RTThreadCtxHooksAreRegistered);
     74RT_EXPORT_SYMBOL(RTThreadCtxHookIsEnabled);
    8475
  • trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c

    r54872 r55863  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Thread-Context Hook, Ring-0 Driver, Linux.
     3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Linux.
    44 */
    55
     
    4242#include "internal/thread.h"
    4343
     44
    4445/*
    45  * Linux kernel 2.6.23 introduced thread-context hooks but RedHat 2.6.18 kernels
     46 * Linux kernel 2.6.23 introduced preemption notifiers but RedHat 2.6.18 kernels
    4647 * got it backported.
    4748 */
     
    5253*******************************************************************************/
    5354/**
    54  * The internal thread-context object.
    55  */
    56 typedef struct RTTHREADCTXINT
    57 {
    58     /** Magic value (RTTHREADCTXINT_MAGIC). */
     55 * The internal hook object for linux.
     56 */
     57typedef struct RTTHREADCTXHOOKINT
     58{
     59    /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */
    5960    uint32_t volatile           u32Magic;
    60     /** The thread handle (owner) for which the context-hooks are registered. */
     61    /** The thread handle (owner) for which the hook is registered. */
    6162    RTNATIVETHREAD              hOwner;
    6263    /** 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. */
    6971    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;
    7474#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 19) && defined(RT_ARCH_AMD64)
    7575    /** Starting with 3.1.19, the linux kernel doesn't restore kernel RFLAGS during
     
    7777    RTCCUINTREG                 fSavedRFlags;
    7878#endif
    79 } RTTHREADCTXINT, *PRTTHREADCTXINT;
     79} RTTHREADCTXHOOKINT;
     80typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT;
    8081
    8182
    8283/**
    83  * Hook function for the thread-preempting event.
     84 * Hook function for the thread schedule out event.
    8485 *
    8586 * @param   pPreemptNotifier    Pointer to the preempt_notifier struct.
    86  * @param   pNext               Pointer to the task that is preempting the
    87  *                              current thread.
     87 * @param   pNext               Pointer to the task that is being scheduled
     88 *                              instead of the current thread.
    8889 *
    8990 * @remarks Called with the rq (runqueue) lock held and with preemption and
     
    9293static void rtThreadCtxHooksLnxSchedOut(struct preempt_notifier *pPreemptNotifier, struct task_struct *pNext)
    9394{
    94     PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
     95    PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier);
    9596#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    9697    RTCCUINTREG fSavedEFlags = ASMGetFlags();
     
    99100
    100101    AssertPtr(pThis);
    101     AssertPtr(pThis->pfnThreadCtxHook);
    102     Assert(pThis->fRegistered);
     102    AssertPtr(pThis->pfnCallback);
     103    Assert(pThis->fEnabled);
    103104    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    104105
    105     pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
     106    pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser);
    106107
    107108#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     
    115116
    116117/**
    117  * Hook function for the thread-resumed event.
     118 * Hook function for the thread schedule in event.
    118119 *
    119120 * @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.
    121122 *
    122123 * @remarks Called without holding the rq (runqueue) lock and with preemption
    123124 *          enabled!
     125 * @todo    r=bird: Preemption is of course disabled when it is called.
    124126 */
    125127static void rtThreadCtxHooksLnxSchedIn(struct preempt_notifier *pPreemptNotifier, int iCpu)
    126128{
    127     PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
     129    PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier);
    128130#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    129131    RTCCUINTREG fSavedEFlags = ASMGetFlags();
     
    132134
    133135    AssertPtr(pThis);
    134     AssertPtr(pThis->pfnThreadCtxHook);
    135     Assert(pThis->fRegistered);
    136 
    137     pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
     136    AssertPtr(pThis->pfnCallback);
     137    Assert(pThis->fEnabled);
     138
     139    pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser);
    138140
    139141#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     
    152154 * @param   pThis   Pointer to the internal thread-context object.
    153155 */
    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;
     156DECLINLINE(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
     167RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
     168{
     169    /*
     170     * Validate input.
     171     */
     172    PRTTHREADCTXHOOKINT pThis;
    166173    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));
    169182    if (RT_UNLIKELY(!pThis))
    170183        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;
    178194    return VINF_SUCCESS;
    179195}
    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);
     196RT_EXPORT_SYMBOL(RTThreadCtxHookCreate);
     197
     198
     199RTDECL(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);
    215210    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)
    219217    {
    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 */
    235221    }
    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}
     228RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy);
     229
     230
     231RTDECL(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),
    254239                    VERR_INVALID_HANDLE);
    255240    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    }
    268255
    269256    return VINF_SUCCESS;
    270257}
    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);
     258RT_EXPORT_SYMBOL(RTThreadCtxHookEnable);
     259
     260
     261RTDECL(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    }
    292280    return VINF_SUCCESS;
    293281}
    294 RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
    295 
    296 
    297 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
    298 {
    299     /*
    300      * Validate input.
    301      */
    302     PRTTHREADCTXINT pThis = hThreadCtx;
    303     if (pThis == NIL_RTTHREADCTX)
     282RT_EXPORT_SYMBOL(RTThreadCtxHookDisable);
     283
     284
     285RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
     286{
     287    /*
     288     * Validate input.
     289     */
     290    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     291    if (pThis == NIL_RTTHREADCTXHOOK)
    304292        return false;
    305293    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;
    309298}
    310299
    311300#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"
    362302#endif   /* Not supported / Not needed */
    363303
  • trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c

    r55860 r55863  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Thread-Context Hook, Ring-0 Driver, Solaris.
     3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Solaris.
    44 */
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4545*******************************************************************************/
    4646/**
    47  * The internal thread-context object.
    48  */
    49 typedef struct RTTHREADCTXINT
    50 {
    51     /** Magic value (RTTHREADCTXINT_MAGIC). */
     47 * The internal hook object for solaris.
     48 */
     49typedef struct RTTHREADCTXHOOKINT
     50{
     51    /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */
    5252    uint32_t volatile           u32Magic;
    5353    /** The thread handle (owner) for which the context-hooks are registered. */
    5454    RTNATIVETHREAD              hOwner;
    55     /** Pointer to the registered thread-context hook. */
    56     PFNRTTHREADCTXHOOK          pfnThreadCtxHook;
    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. */
    5858    void                       *pvUser;
    59     /** Whether this handle has any hooks registered or not. */
    60     bool volatile               fRegistered;
     59    /** Whether the hook is enabled or not. */
     60    bool volatile               fEnabled;
    6161    /** Number of references to this object. */
    6262    uint32_t volatile           cRefs;
    63 } RTTHREADCTXINT, *PRTTHREADCTXINT;
     63} RTTHREADCTXHOOKINT;
     64typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT;
    6465
    6566
     
    6768*   Defined Constants And Macros                                               *
    6869*******************************************************************************/
    69 /** Validates a thread-context hook handle and returns rc if not valid. */
     70/** Validates a hook handle and returns rc if not valid. */
    7071#define RTTHREADCTX_VALID_RETURN_RC(pThis, rc) \
    7172    do { \
    7273        AssertPtrReturn((pThis), (rc)); \
    73         AssertReturn((pThis)->u32Magic == RTTHREADCTXINT_MAGIC, (rc)); \
     74        AssertReturn((pThis)->u32Magic == RTTHREADCTXHOOKINT_MAGIC, (rc)); \
    7475        AssertReturn((pThis)->cRefs > 0, (rc)); \
    7576    } while (0)
     
    7778
    7879/**
    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.
    8383 *
    8484 * @remarks Called with the with preemption disabled!
    8585 */
    86 static void rtThreadCtxHooksSolPreempting(void *pvThreadCtxInt)
    87 {
    88     PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
     86static void rtThreadCtxHookSolOut(void *pvThreadCtxInt)
     87{
     88    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
    8989    AssertPtr(pThis);
    9090    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);
    9697    }
    9798}
     
    99100
    100101/**
    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 */
     106static void rtThreadCtxHookSolIn(void *pvThreadCtxInt)
     107{
     108    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
    109109    AssertPtr(pThis);
    110110    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);
    116117    }
    117118}
     
    121122 * Hook function for the thread-free event.
    122123 *
    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.
    125128 * @param   fIsExec             Whether this event is triggered due to exec().
    126129 */
    127 static void rtThreadCtxHooksSolFree(void *pvThreadCtxInt, int fIsExec)
    128 {
    129     PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
     130static void rtThreadCtxHookSolFree(void *pvThreadCtxInt, int fIsExec)
     131{
     132    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
    130133    AssertPtrReturnVoid(pThis);
    131     AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_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));
    132135
    133136    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
    135148    {
    136149        /* 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
     155RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
     156{
     157    /*
     158     * Validate input.
     159     */
     160    PRTTHREADCTXHOOKINT pThis;
    154161    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));
    157169    if (RT_UNLIKELY(!pThis))
    158170        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
    167181     * invoke the consumer's hook or not.
    168182     */
     
    171185        g_rtSolThreadCtx.Install.pfnSol_installctx_old(curthread,
    172186                                                       pThis,
    173                                                        rtThreadCtxHooksSolPreempting,
    174                                                        rtThreadCtxHooksSolResumed,
    175                                                        NULL,                          /* fork */
    176                                                        NULL,                          /* lwp_create */
    177                                                        rtThreadCtxHooksSolFree);
     187                                                       rtThreadCtxHookSolOut,   /* save */
     188                                                       rtThreadCtxHookSolIn,    /* restore */
     189                                                       NULL,                    /* fork */
     190                                                       NULL,                    /* lwp_create */
     191                                                       rtThreadCtxHookSolFree);
    178192    }
    179193    else
     
    181195        g_rtSolThreadCtx.Install.pfnSol_installctx(curthread,
    182196                                                   pThis,
    183                                                    rtThreadCtxHooksSolPreempting,
    184                                                    rtThreadCtxHooksSolResumed,
    185                                                    NULL,                              /* fork */
    186                                                    NULL,                              /* lwp_create */
    187                                                    NULL,                              /* exit */
    188                                                    rtThreadCtxHooksSolFree);
    189     }
    190 
    191     *phThreadCtx = pThis;
     197                                                   rtThreadCtxHookSolOut,       /* save */
     198                                                   rtThreadCtxHookSolIn,        /* restore */
     199                                                   NULL,                        /* fork */
     200                                                   NULL,                        /* lwp_create */
     201                                                   NULL,                        /* exit */
     202                                                   rtThreadCtxHookSolFree);
     203    }
     204
     205    *phCtxHook = pThis;
    192206    return VINF_SUCCESS;
    193207}
    194208
    195209
    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);
     210RTDECL(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);
    214219    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     */
    217230    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
    218 
    219231    if (   cRefs == 1
    220232        && pThis->hOwner == RTThreadNativeSelf())
    221233    {
    222234        /*
    223          * removectx() will invoke rtThreadCtxHooksSolFree() and there is no way to bypass it and still use
    224          * rtThreadCtxHooksSolFree() 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.
    225237         *
    226238         * When this function is called from the owner thread and is the last reference, we call removectx() which
    227          * will invoke rtThreadCtxHooksSolFree() 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.
    228240         *
    229241         * When the function is called from a different thread, we simply decrement the reference. Whenever the
    230          * ring-0 thread dies, Solaris will call rtThreadCtxHooksSolFree() which will free the hook object.
     242         * ring-0 thread dies, Solaris will call rtThreadCtxHookSolFree() which will free the hook object.
    231243         */
    232244        int rc;
     
    235247            rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread,
    236248                                                              pThis,
    237                                                               rtThreadCtxHooksSolPreempting,
    238                                                               rtThreadCtxHooksSolResumed,
    239                                                               NULL,                          /* fork */
    240                                                               NULL,                          /* lwp_create */
    241                                                               rtThreadCtxHooksSolFree);
     249                                                              rtThreadCtxHookSolOut,    /* save */
     250                                                              rtThreadCtxHookSolIn,     /* restore */
     251                                                              NULL,                     /* fork */
     252                                                              NULL,                     /* lwp_create */
     253                                                              rtThreadCtxHookSolFree);
    242254        }
    243255        else
     
    245257            rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread,
    246258                                                          pThis,
    247                                                           rtThreadCtxHooksSolPreempting,
    248                                                           rtThreadCtxHooksSolResumed,
    249                                                           NULL,                              /* fork */
    250                                                           NULL,                              /* lwp_create */
    251                                                           NULL,                              /* exit */
    252                                                           rtThreadCtxHooksSolFree);
     259                                                          rtThreadCtxHookSolOut,        /* save */
     260                                                          rtThreadCtxHookSolIn,         /* restore */
     261                                                          NULL,                         /* fork */
     262                                                          NULL,                         /* lwp_create */
     263                                                          NULL,                         /* exit */
     264                                                          rtThreadCtxHookSolFree);
    253265        }
    254266        AssertMsg(rc, ("removectx() failed. rc=%d\n", rc));
     
    267279         */
    268280        Assert(pThis->hOwner != RTThreadNativeSelf());
    269         ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
     281        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
    270282        RTMemFree(pThis);
    271283    }
     
    275287
    276288
    277 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
     289RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
    278290{
    279291    /*
    280292     * Validate input.
    281293     */
    282     PRTTHREADCTXINT pThis = hThreadCtx;
    283     if (pThis == NIL_RTTHREADCTX)
    284         return VERR_INVALID_HANDLE;
     294    PRTTHREADCTXHOOKINT pThis = hCtxHook;
    285295    AssertPtr(pThis);
    286     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_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),
    287297                    VERR_INVALID_HANDLE);
    288298    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;
    296305
    297306    return VINF_SUCCESS;
     
    299308
    300309
    301 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
     310RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
    302311{
    303312    /*
    304313     * Validate input.
    305314     */
    306     PRTTHREADCTXINT 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    }
    319328
    320329    return VINF_SUCCESS;
     
    322331
    323332
    324 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
     333RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
    325334{
    326335    /*
    327336     * Validate input.
    328337     */
    329     PRTTHREADCTXINT pThis = hThreadCtx;
    330     if (pThis == NIL_RTTHREADCTX)
     338    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     339    if (pThis == NIL_RTTHREADCTXHOOK)
    331340        return false;
    332341    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  
    4949    RTCPUID             uSourceCpuId;
    5050    RTNATIVETHREAD      hSourceThread;
    51     RTTHREADCTX         hThreadCtx;
    5251
    5352    /* For RTTHREADCTXEVENT_PREEMPTING. */
     
    8281    switch (enmEvent)
    8382    {
    84         case RTTHREADCTXEVENT_PREEMPTING:
     83        case RTTHREADCTXEVENT_OUT:
    8584        {
    8685            ASMAtomicWriteBool(&pData->fPreemptingInvoked, true);
     
    119118        }
    120119
    121         case RTTHREADCTXEVENT_RESUMED:
     120        case RTTHREADCTXEVENT_IN:
    122121        {
    123122            ASMAtomicWriteBool(&pData->fResumedInvoked, true);
     
    302301            }
    303302
    304             bool fRegistered = RTThreadCtxHooksAreRegistered(NIL_RTTHREADCTX);
     303            bool fRegistered = RTThreadCtxHookIsEnabled(NIL_RTTHREADCTXHOOK);
    305304            if (fRegistered)
    306305            {
    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");
    327307                break;
    328308            }
     
    331311            AssertReturn(pCtxData, VERR_NO_MEMORY);
    332312            pCtxData->u32Magic           = TSTRTR0THREADCTXDATA_MAGIC;
    333             pCtxData->hThreadCtx         = hThreadCtx;
    334313            pCtxData->fPreemptingSuccess = false;
    335314            pCtxData->fPreemptingInvoked = false;
     
    339318            RT_ZERO(pCtxData->achResult);
    340319
     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
    341340            RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
    342341            RTThreadPreemptDisable(&PreemptState);
     
    345344            pCtxData->uSourceCpuId       = RTMpCpuId();
    346345
    347             rc = RTThreadCtxHooksRegister(hThreadCtx, &tstRTR0ThreadCtxHook, pCtxData);
     346            rc = RTThreadCtxHookEnable(hThreadCtx);
    348347            if (RT_FAILURE(rc))
    349348            {
    350349                RTThreadPreemptRestore(&PreemptState);
    351350                RTMemFree(pCtxData);
    352                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRegister returns %Rrc", rc);
    353                 break;
    354             }
    355 
    356             fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
     351                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookEnable returns %Rrc", rc);
     352                break;
     353            }
     354
     355            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
    357356            if (!fRegistered)
    358357            {
    359358                RTThreadPreemptRestore(&PreemptState);
    360359                RTMemFree(pCtxData);
    361                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered return false when hooks are supposedly registered");
     360                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return false when hooks are supposedly registered");
    362361                break;
    363362            }
     
    428427            }
    429428
    430             RTThreadCtxHooksDeregister(hThreadCtx);
    431 
    432             fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
     429            RTThreadCtxHookDisable(hThreadCtx);
     430
     431            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
    433432            if (fRegistered)
    434433            {
    435434                RTMemFree(pCtxData);
    436                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered return true when hooks are deregistered");
     435                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return true when hooks are deregistered");
    437436                break;
    438437            }
    439438
    440439            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);
    444443
    445444            RTMemFree(pCtxData);
  • trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp

    r54191 r55863  
    889889                                        pGVMM->cEMTs += cCpus;
    890890
    891                                         rc = VMMR0ThreadCtxHooksCreate(&pVM->aCpus[0]);
     891                                        rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[0]);
    892892                                        if (RT_SUCCESS(rc))
    893893                                        {
     
    11231123             *        solution for not deregistering hooks everytime we're leaving HMR0
    11241124             *        context. */
    1125             VMMR0ThreadCtxHooksRelease(&pVM->aCpus[idCpu]);
     1125            VMMR0ThreadCtxHookDestroyForEmt(&pVM->aCpus[idCpu]);
    11261126        }
    11271127
     
    13511351    pVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf();
    13521352
    1353     rc = VMMR0ThreadCtxHooksCreate(&pVM->aCpus[idCpu]);
    1354     return rc;
     1353    return VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[idCpu]);
    13551354}
    13561355
  • trunk/src/VBox/VMM/VMMR0/HMR0.cpp

    r55755 r55863  
    13661366
    13671367#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
    1368     AssertReturn(!VMMR0ThreadCtxHooksAreRegistered(pVCpu), VERR_HM_IPE_5);
     1368    AssertReturn(!VMMR0ThreadCtxHookIsEnabled(pVCpu), VERR_HM_IPE_5);
    13691369    bool fStartedSet = PGMR0DynMapStartOrMigrateAutoSet(pVCpu);
    13701370#endif
     
    14711471
    14721472#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
    1473     AssertReturn(!VMMR0ThreadCtxHooksAreRegistered(pVCpu), VERR_HM_IPE_4);
     1473    AssertReturn(!VMMR0ThreadCtxHookIsEnabled(pVCpu), VERR_HM_IPE_4);
    14741474    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    14751475    PGMRZDynMapStartAutoSet(pVCpu);
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r55830 r55863  
    121121
    122122/** Assert that preemption is disabled or covered by thread-context hooks. */
    123 #define HMSVM_ASSERT_PREEMPT_SAFE()           Assert(   VMMR0ThreadCtxHooksAreRegistered(pVCpu) \
     123#define HMSVM_ASSERT_PREEMPT_SAFE()           Assert(   VMMR0ThreadCtxHookIsEnabled(pVCpu) \
    124124                                                     || !RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    125125
    126126/** Assert that we haven't migrated CPUs when thread-context hooks are not
    127127 *  used. */
    128 #define HMSVM_ASSERT_CPU_SAFE()               AssertMsg(   VMMR0ThreadCtxHooksAreRegistered(pVCpu) \
     128#define HMSVM_ASSERT_CPU_SAFE()               AssertMsg(   VMMR0ThreadCtxHookIsEnabled(pVCpu) \
    129129                                                        || pVCpu->hm.s.idEnteredCpu == RTMpCpuId(), \
    130130                                                        ("Illegal migration! Entered on CPU %u Current %u\n", \
     
    17411741    switch (enmEvent)
    17421742    {
    1743         case RTTHREADCTXEVENT_PREEMPTING:
     1743        case RTTHREADCTXEVENT_OUT:
    17441744        {
    17451745            Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    1746             Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
     1746            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
    17471747            VMCPU_ASSERT_EMT(pVCpu);
    17481748
     
    17691769        }
    17701770
    1771         case RTTHREADCTXEVENT_RESUMED:
     1771        case RTTHREADCTXEVENT_IN:
    17721772        {
    17731773            Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    1774             Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
     1774            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
    17751775            VMCPU_ASSERT_EMT(pVCpu);
    17761776
     
    21402140     */
    21412141
     2142    /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
    21422143    /* Deregister hook now that we've left HM context before re-enabling preemption. */
    2143     VMMR0ThreadCtxHooksDeregister(pVCpu);
     2144    VMMR0ThreadCtxHookDisable(pVCpu);
    21442145
    21452146    /* Leave HM context. This takes care of local init (term). */
     
    21982199
    21992200        /* 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);
    22012203
    22022204        /* Leave HM context. This takes care of local init (term). */
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r55830 r55863  
    184184
    185185/** Assert that preemption is disabled or covered by thread-context hooks. */
    186 #define HMVMX_ASSERT_PREEMPT_SAFE()       Assert(   VMMR0ThreadCtxHooksAreRegistered(pVCpu)   \
     186#define HMVMX_ASSERT_PREEMPT_SAFE()       Assert(   VMMR0ThreadCtxHookIsEnabled(pVCpu)   \
    187187                                                 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    188188
    189189/** Assert that we haven't migrated CPUs when thread-context hooks are not
    190190 *  used. */
    191 #define HMVMX_ASSERT_CPU_SAFE()           AssertMsg(   VMMR0ThreadCtxHooksAreRegistered(pVCpu) \
     191#define HMVMX_ASSERT_CPU_SAFE()           AssertMsg(   VMMR0ThreadCtxHookIsEnabled(pVCpu) \
    192192                                                    || pVCpu->hm.s.idEnteredCpu == RTMpCpuId(), \
    193193                                                    ("Illegal migration! Entered on CPU %u Current %u\n", \
     
    72437243    /** @todo Deregistering here means we need to VMCLEAR always
    72447244     *        (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);
    72467247
    72477248    /* Leave HM context. This takes care of local init (term). */
     
    73767377         * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
    73777378         */
    7378         RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; \
    73797379        VMMRZCallRing3RemoveNotification(pVCpu);
    73807380        VMMRZCallRing3Disable(pVCpu);
     7381        RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
    73817382        RTThreadPreemptDisable(&PreemptState);
    73827383
     
    74087409        }
    74097410
    7410         VMMR0ThreadCtxHooksDeregister(pVCpu);
     7411        /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
     7412        VMMR0ThreadCtxHookDisable(pVCpu);
    74117413        HMR0LeaveCpu(pVCpu);
    74127414        RTThreadPreemptRestore(&PreemptState);
     
    82228224    switch (enmEvent)
    82238225    {
    8224         case RTTHREADCTXEVENT_PREEMPTING:
     8226        case RTTHREADCTXEVENT_OUT:
    82258227        {
    82268228            Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    8227             Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
     8229            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
    82288230            VMCPU_ASSERT_EMT(pVCpu);
    82298231
     
    82568258        }
    82578259
    8258         case RTTHREADCTXEVENT_RESUMED:
     8260        case RTTHREADCTXEVENT_IN:
    82598261        {
    82608262            Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    8261             Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
     8263            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
    82628264            VMCPU_ASSERT_EMT(pVCpu);
    82638265
     
    1006010062    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
    1006110063    /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
    10062     if (VMMR0ThreadCtxHooksAreRegistered(pVCpu))
     10064    if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
    1006310065        return VINF_SUCCESS;
    1006410066    return VINF_EM_RAW_INTERRUPT;
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r55715 r55863  
    447447
    448448/**
    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 #endif
    469 
    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 this
    525  * 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 /**
    549449 * VMM ring-0 thread-context callback.
    550450 *
     
    563463    switch (enmEvent)
    564464    {
    565         case RTTHREADCTXEVENT_RESUMED:
     465        case RTTHREADCTXEVENT_IN:
    566466        {
    567467            /*
     
    571471             * ad infinitum). Let's just disable preemption for now...
    572472             */
    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);
    574478
    575479            /* We need to update the VCPU <-> host CPU mapping. */
     
    589493
    590494            /* Restore preemption. */
    591             HM_RESTORE_PREEMPT();
     495            RTThreadPreemptRestore(&ParanoidPreemptState);
    592496            break;
    593497        }
    594498
    595         case RTTHREADCTXEVENT_PREEMPTING:
     499        case RTTHREADCTXEVENT_OUT:
    596500        {
    597501            /* Invoke the HM-specific thread-context callback. */
     
    612516            break;
    613517    }
     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 */
     532VMMR0_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 */
     556VMMR0_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 */
     572VMMR0_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 */
     609DECLINLINE(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 */
     621VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPU pVCpu)
     622{
     623    return vmmR0ThreadCtxHookIsEnabled(pVCpu);
    614624}
    615625
     
    9931003             * Disable preemption.
    9941004             */
    995             Assert(!VMMR0ThreadCtxHooksAreRegistered(pVCpu));
     1005            Assert(!vmmR0ThreadCtxHookIsEnabled(pVCpu));
    9961006            RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
    9971007            RTThreadPreemptDisable(&PreemptState);
     
    10381048                     * Register thread-context hooks if required.
    10391049                     */
    1040                     if (    VMMR0ThreadCtxHooksAreCreated(pVCpu)
    1041                         && !VMMR0ThreadCtxHooksAreRegistered(pVCpu))
     1050                    if (    pVCpu->vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK
     1051                        && !RTThreadCtxHookIsEnabled(pVCpu->vmm.s.hCtxHook))
    10421052                    {
    1043                         rc = VMMR0ThreadCtxHooksRegister(pVCpu, vmmR0ThreadCtxCallback);
     1053                        rc = RTThreadCtxHookEnable(pVCpu->vmm.s.hCtxHook);
    10441054                        AssertRC(rc);
    10451055                    }
     
    10571067                         * we're in HM context.
    10581068                         */
    1059                         if (VMMR0ThreadCtxHooksAreRegistered(pVCpu))
     1069                        if (vmmR0ThreadCtxHookIsEnabled(pVCpu))
    10601070                        {
    10611071                            fPreemptRestored = true;
     
    10801090                            rc = VERR_VMM_WRONG_HM_VMCPU_STATE;
    10811091                        }
    1082                         else if (RT_UNLIKELY(VMMR0ThreadCtxHooksAreRegistered(pVCpu)))
     1092                        else if (RT_UNLIKELY(vmmR0ThreadCtxHookIsEnabled(pVCpu)))
    10831093                        {
    10841094                            pVM->vmm.s.szRing0AssertMsg1[0] = '\0';
     
    10911101                    }
    10921102                    STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
     1103
     1104                    /** @todo shouldn't we disable the ctx hook here??? */
    10931105                }
    10941106                /*
  • trunk/src/VBox/VMM/VMMR3/VMM.cpp

    r55568 r55863  
    541541
    542542    /* 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.hR0ThreadCtx != NIL_RTTHREADCTX)
     543    if (pVM->aCpus[0].vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK)
    544544        LogRel(("VMM: Thread-context hooks enabled!\n"));
    545545    else
  • trunk/src/VBox/VMM/include/HMInternal.h

    r55756 r55863  
    221221#define HM_VTX_TOTAL_DEVHEAP_MEM        (HM_EPT_IDENTITY_PG_TABLE_SIZE + HM_VTX_TSS_SIZE)
    222222
     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
    223242/** Enable for TPR guest patching. */
    224243#define VBOX_HM_WITH_GUEST_PATCHING
    225244
    226 /** HM SSM version
     245/** @name HM saved state versions
     246 * @{
    227247 */
    228248#ifdef VBOX_HM_WITH_GUEST_PATCHING
     
    234254#endif
    235255#define HM_SAVED_STATE_VERSION_2_0_X            3
     256/** @} */
    236257
    237258/**
  • trunk/src/VBox/VMM/include/VMMInternal.h

    r53466 r55863  
    420420    R0PTRTYPE(PVMMR0LOGGER)     pR0LoggerR0;
    421421
    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;
    431424
    432425    /** @name Rendezvous
     
    435428     *  attempts at recursive rendezvous. */
    436429    bool volatile               fInRendezvous;
    437     bool                        afPadding[HC_ARCH_BITS == 32 ? 3 : 7];
     430    bool                        afPadding[HC_ARCH_BITS == 32 ? 3+4 : 7+8];
    438431    /** @} */
    439432
    440     /** @name Raw-mode context tracting data.
     433    /** @name Raw-mode context tracing data.
    441434     * @{ */
    442435    SUPDRVTRACERUSRCTX          TracerCtx;
  • trunk/src/VBox/VMM/include/VMMInternal.mac

    r48499 r55863  
    108108        .pR0LoggerR0            RTR0PTR_RES 1
    109109
    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
    116111
    117112        .fInRendezvous          resb 1
    118113%if HC_ARCH_BITS == 32
    119         .afPadding              resb 3
     114        .afPadding              resb 3+4
    120115%else
    121         .afPadding              resb 7
     116        .afPadding              resb 7+8
    122117%endif
    123118
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette