Index: /trunk/include/VBox/vmm/hm.h
===================================================================
--- /trunk/include/VBox/vmm/hm.h	(revision 55862)
+++ /trunk/include/VBox/vmm/hm.h	(revision 55863)
@@ -182,17 +182,4 @@
 VMMR0_INT_DECL(void)            HMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext,
                                                           unsigned uPort, unsigned uAndVal, unsigned cbSize);
-#ifdef VBOX_STRICT
-# define HM_DISABLE_PREEMPT() \
-    RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \
-    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD) || VMMR0ThreadCtxHooksAreRegistered(pVCpu)); \
-    RTThreadPreemptDisable(&PreemptStateInternal);
-#else
-# define HM_DISABLE_PREEMPT() \
-    RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \
-    RTThreadPreemptDisable(&PreemptStateInternal);
-#endif /* VBOX_STRICT */
-# define HM_RESTORE_PREEMPT()   do { RTThreadPreemptRestore(&PreemptStateInternal); } while(0)
-
-
 VMMR0_INT_DECL(int)             HMR0SetupVM(PVM pVM);
 VMMR0_INT_DECL(int)             HMR0RunGuestCode(PVM pVM, PVMCPU pVCpu);
Index: /trunk/include/VBox/vmm/vmm.h
===================================================================
--- /trunk/include/VBox/vmm/vmm.h	(revision 55862)
+++ /trunk/include/VBox/vmm/vmm.h	(revision 55863)
@@ -512,10 +512,8 @@
 VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPU pVCpu);
 VMMR0_INT_DECL(bool) VMMR0IsInRing3LongJump(PVMCPU pVCpu);
-VMMR0_INT_DECL(int)  VMMR0ThreadCtxHooksCreate(PVMCPU pVCpu);
-VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksRelease(PVMCPU pVCpu);
-VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreCreated(PVMCPU pVCpu);
-VMMR0_INT_DECL(int)  VMMR0ThreadCtxHooksRegister(PVMCPU pVCpu, PFNRTTHREADCTXHOOK pfnHook);
-VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksDeregister(PVMCPU pVCpu);
-VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreRegistered(PVMCPU pVCpu);
+VMMR0_INT_DECL(int)  VMMR0ThreadCtxHookCreateForEmt(PVMCPU pVCpu);
+VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDestroyForEmt(PVMCPU pVCpu);
+VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDisable(PVMCPU pVCpu);
+VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPU pVCpu);
 
 # ifdef LOG_ENABLED
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 55862)
+++ /trunk/include/iprt/mangling.h	(revision 55863)
@@ -1682,10 +1682,9 @@
 # define RTThreadCreateF                                RT_MANGLER(RTThreadCreateF)
 # define RTThreadCreateV                                RT_MANGLER(RTThreadCreateV)
-# define RTThreadCtxHooksAreRegistered                  RT_MANGLER(RTThreadCtxHooksAreRegistered)  /* r0drv */
-# define RTThreadCtxHooksCreate                         RT_MANGLER(RTThreadCtxHooksCreate)         /* r0drv */
-# define RTThreadCtxHooksDeregister                     RT_MANGLER(RTThreadCtxHooksDeregister)     /* r0drv */
-# define RTThreadCtxHooksRegister                       RT_MANGLER(RTThreadCtxHooksRegister)       /* r0drv */
-# define RTThreadCtxHooksRelease                        RT_MANGLER(RTThreadCtxHooksRelease)        /* r0drv */
-# define RTThreadCtxHooksRetain                         RT_MANGLER(RTThreadCtxHooksRetain)         /* r0drv */
+# define RTThreadCtxHookIsEnabled                       RT_MANGLER(RTThreadCtxHookIsEnabled)    /* r0drv */
+# define RTThreadCtxHookCreate                          RT_MANGLER(RTThreadCtxHookCreate)       /* r0drv */
+# define RTThreadCtxHookDestroy                         RT_MANGLER(RTThreadCtxHookDestroy)      /* r0drv */
+# define RTThreadCtxHookDisable                         RT_MANGLER(RTThreadCtxHookDisable)      /* r0drv */
+# define RTThreadCtxHookEnable                          RT_MANGLER(RTThreadCtxHookEnable)       /* r0drv */
 # define RTThreadFromNative                             RT_MANGLER(RTThreadFromNative)
 # define RTThreadGetAffinity                            RT_MANGLER(RTThreadGetAffinity)
Index: /trunk/include/iprt/thread.h
===================================================================
--- /trunk/include/iprt/thread.h	(revision 55862)
+++ /trunk/include/iprt/thread.h	(revision 55863)
@@ -588,12 +588,14 @@
 
 /**
- * Thread-context events.
+ * Thread context swithcing events.
  */
 typedef enum RTTHREADCTXEVENT
 {
-    /** This thread is about to be preempted. */
-    RTTHREADCTXEVENT_PREEMPTING = 0,
-    /** This thread has just been resumed. */
-    RTTHREADCTXEVENT_RESUMED,
+    /** This thread is being scheduled out on the current CPU (includes preemption,
+     * waiting, sleep and whatever else may trigger scheduling). */
+    RTTHREADCTXEVENT_OUT = 0,
+    /** This thread is being scheduled in on the current CPU and will resume
+     * execution. */
+    RTTHREADCTXEVENT_IN,
     /** The usual 32-bit size hack. */
     RTTHREADCTXEVENT_32BIT_HACK = 0x7fffffff
@@ -601,91 +603,87 @@
 
 /**
- * Thread-context hook.
- *
- * @returns IPRT status code.
- * @param   enmEvent    The thread-context event.
+ * Thread context switching hook callback.
+ *
+ * This hook function is called when a thread is scheduled and preempted.  Check
+ * @a enmEvent to see which it is.  Since the function is being called from
+ * hooks inside the scheduler, it is limited what you can do from this function.
+ * Do NOT acquire locks, sleep or yield the thread for instance.  IRQ safe
+ * spinlocks are fine though.
+ *
+ * @returns IPRT status code.
+ * @param   enmEvent    The thread-context event.  Please quitely ignore unknown
+ *                      events, we may add more (thread exit, ++) later.
  * @param   pvUser      User argument.
- *
- * @remarks This function may be called under different contexts, i.e. with
- *          different locks held, with/without preemption disabled depending on
- *          the event in @a enmEvent.
  */
 typedef DECLCALLBACK(void) FNRTTHREADCTXHOOK(RTTHREADCTXEVENT enmEvent, void *pvUser);
-/** Pointer to a thread-context hook. */
+/** Pointer to a context switching hook. */
 typedef FNRTTHREADCTXHOOK *PFNRTTHREADCTXHOOK;
 
 /**
- * Initializes a thread-context hook for the current thread.
- *
- * This must be called once per-thread before using RTThreadCtxHooksRegister().
- *
- * @returns IPRT status code.
- * @param   phThreadCtx         Where to store the thread-context handle.
- *
- * @remarks This must be called with preemption enabled!
- */
-RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx);
-
-/**
- * Retains a new reference to a thread-context hook.
- *
- * @returns New reference count.
- *          UINT32_MAX is returned if the handle is invalid (asserted).
- * @param   phThreadCtx         Pointer to the thread-context handle.
- *
- * @remarks This can be called from any thread. Can be called with preemption
- *          disabled.
- */
-RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx);
-
-/**
- * Releases a reference to a thread-context hook.
- *
- * @returns New reference count.
- * @retval  0 if the thread-context hook was freed or @a hThreadCtx is
- *          NIL_RTTHREADCTX.
- * @retval  UINT32_MAX is returned if the handle is invalid (asserted).
- *
- * @param   hThreadCtx          The thread-context handle.
- *
- * @remarks This can be called from any thread but must be called with
- *          preemption enabled!
- */
-RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx);
-
-/**
- * Registers a thread-context hook for the current thread to receive
- * notifications for all supported thread-context events.
- *
- * @returns IPRT status code.
- * @param   hThreadCtx          The thread-context handle.
- * @param   pfnThreadHook       Pointer to a thread-context hook (a callback)
- *                              for all thread-context events.
- * @param   pvUser              User argument (optional, can be NULL).
- *
- * @remarks Can be called with preemption disabled.
- */
-RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadHook, void *pvUser);
-
-/**
- * Deregisters the thread-context hook for the current thread.
- *
- * @returns IPRT status code.
- * @param   hThreadCtx          The thread-context handle.
- *
- * @remarks Can be called with preemption disabled.
- */
-RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx);
-
-/**
- * Are thread-context hooks registered for the thread?
+ * Initializes a thread context switching hook for the current thread.
+ *
+ * The hook is created as disabled, use RTThreadCtxHookEnable to enable it.
+ *
+ * @returns IPRT status code.
+ * @param   phCtxHook       Where to store the hook handle.
+ * @param   fFlags          Reserved for future extensions, must be zero.
+ * @param   pfnCallback     Pointer to a the hook function (callback) that
+ *                          should be called for all context switching events
+ *                          involving the current thread.
+ * @param   pvUser          User argument that will be passed to @a pfnCallback.
+ * @remarks Preemption must be enabled.
+ */
+RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser);
+
+/**
+ * Destroys a thread context switching hook.
+ *
+ * Caller must make sure the hook is disabled before the final reference is
+ * released.  Recommended to call this on the owning thread, otherwise the
+ * memory backing it may on some systems only be released when the thread
+ * terminates.
+ *
+ * @returns IPRT status code.
+ *
+ * @param   hCtxHook        The context hook handle.  NIL_RTTHREADCTXHOOK is
+ *                          ignored and the function will return VINF_SUCCESS.
+ * @remarks Preemption must be enabled.
+ * @remarks Do not call from FNRTTHREADCTXHOOK.
+ */
+RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook);
+
+/**
+ * Enables the context switching hooks for the current thread.
+ *
+ * @returns IPRT status code.
+ * @param   hCtxHook        The context hook handle.
+ * @remarks Should be called with preemption disabled.
+ */
+RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook);
+
+/**
+ * Disables the thread context switching hook for the current thread.
+ *
+ * Will not assert or fail if called twice or with a NIL handle.
+ *
+ * @returns IPRT status code.
+ * @param   hCtxHook        The context hook handle. NIL_RTTHREADCTXHOOK is
+ *                          ignored and the function wil return VINF_SUCCESS.
+ * @remarks Should be called with preemption disabled.
+ * @remarks Do not call from FNRTTHREADCTXHOOK.
+ */
+RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook);
+
+/**
+ * Is the thread context switching hook enabled?
  *
  * @returns true if registered, false if not supported or not registered.
- * @param   hThreadCtx          The thread-context handle.
- *
- * @remarks Can be called from any thread (but possibility of races when
- *          it's not the current thread!)
- */
-RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx);
+ * @param   hCtxHook        The context hook handle.   NIL_RTTHREADCTXHOOK is
+ *                          ignored and the function will return false.
+ *
+ * @remarks Can be called from any thread, though is naturally subject to races
+ *          when not called from the thread associated with the hook.
+ */
+RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook);
 
 # endif /* IN_RING0 */
Index: /trunk/include/iprt/types.h
===================================================================
--- /trunk/include/iprt/types.h	(revision 55862)
+++ /trunk/include/iprt/types.h	(revision 55863)
@@ -1763,10 +1763,10 @@
 #define NIL_RTTHREAD                                0
 
-/** Thread-context handle.*/
-typedef R0PTRTYPE(struct RTTHREADCTXINT *)          RTTHREADCTX;
-/** Pointer to thread handle. */
-typedef RTTHREADCTX                                *PRTTHREADCTX;
-/** Nil thread-context handle. */
-#define NIL_RTTHREADCTX                             0
+/** Thread context switching hook handle.   */
+typedef R0PTRTYPE(struct RTTHREADCTXHOOKINT *)      RTTHREADCTXHOOK;
+/** Pointer to Thread context switching hook handle. */
+typedef RTTHREADCTXHOOK                            *PRTTHREADCTXHOOK;
+/** Nil Thread context switching hook handle. */
+#define NIL_RTTHREADCTXHOOK                         ((RTTHREADCTXHOOK)0)
 
 /** A TLS index. */
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 55862)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 55863)
@@ -360,10 +360,9 @@
     { "RTStrPrintfV",                           (void *)RTStrPrintfV },
     { "RTThreadCreate",                         (void *)RTThreadCreate },
-    { "RTThreadCtxHooksAreRegistered",          (void *)RTThreadCtxHooksAreRegistered },
-    { "RTThreadCtxHooksCreate",                 (void *)RTThreadCtxHooksCreate },
-    { "RTThreadCtxHooksDeregister",             (void *)RTThreadCtxHooksDeregister },
-    { "RTThreadCtxHooksRegister",               (void *)RTThreadCtxHooksRegister },
-    { "RTThreadCtxHooksRelease",                (void *)RTThreadCtxHooksRelease },
-    { "RTThreadCtxHooksRetain",                 (void *)RTThreadCtxHooksRetain },
+    { "RTThreadCtxHookIsEnabled",               (void *)RTThreadCtxHookIsEnabled },
+    { "RTThreadCtxHookCreate",                  (void *)RTThreadCtxHookCreate },
+    { "RTThreadCtxHookDestroy",                 (void *)RTThreadCtxHookDestroy },
+    { "RTThreadCtxHookDisable",                 (void *)RTThreadCtxHookDisable },
+    { "RTThreadCtxHookEnable",                  (void *)RTThreadCtxHookEnable },
     { "RTThreadGetName",                        (void *)RTThreadGetName },
     { "RTThreadGetNative",                      (void *)RTThreadGetNative },
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 55862)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 55863)
@@ -215,5 +215,5 @@
  *          - (nothing)
  */
-#define SUPDRV_IOC_VERSION                              0x00200000
+#define SUPDRV_IOC_VERSION                              0x00220000
 
 /** SUP_IOCTL_COOKIE. */
Index: /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 55862)
+++ /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 55863)
@@ -194,4 +194,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c=>r0drv/generic/semspinmutex-r0drv-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp=>r0drv/generic/threadctxhooks-r0drv-generic.cpp \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \
     ${PATH_ROOT}/src/VBox/Runtime/VBox/log-vbox.cpp=>VBox/log-vbox.c \
Index: /trunk/src/VBox/Runtime/include/internal/magics.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/magics.h	(revision 55862)
+++ /trunk/src/VBox/Runtime/include/internal/magics.h	(revision 55863)
@@ -193,6 +193,6 @@
 /** RTTESTINT::u32Magic value. (Daniel Kehlmann) */
 #define RTTESTINT_MAGIC                 UINT32_C(0x19750113)
-/** RTTHREADCTXINT::u32Magic value. (Dennis MacAlistair Ritchie) */
-#define RTTHREADCTXINT_MAGIC            UINT32_C(0x19410909)
+/** RTTHREADCTXHOOKINT::u32Magic value. (Dennis MacAlistair Ritchie) */
+#define RTTHREADCTXHOOKINT_MAGIC        UINT32_C(0x19410909)
 /** RTTHREADINT::u32Magic value. (Gilbert Keith Chesterton) */
 #define RTTHREADINT_MAGIC               UINT32_C(0x18740529)
Index: /trunk/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp	(revision 55862)
+++ /trunk/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp	(revision 55863)
@@ -1,9 +1,9 @@
 /* $Id$ */
 /** @file
- * IPRT - Thread-Context Hooks, Ring-0 Driver, Generic.
+ * IPRT - Thread Context Switching Hook, Ring-0 Driver, Generic.
  */
 
 /*
- * Copyright (C) 2013 Oracle Corporation
+ * Copyright (C) 2013-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -34,51 +34,42 @@
 #include "internal/iprt.h"
 
-RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
+RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
 {
-    NOREF(phThreadCtx);
-    return VERR_NOT_SUPPORTED;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
-{
-    NOREF(hThreadCtx);
-    return UINT32_MAX;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease);
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
-{
-    NOREF(hThreadCtx);
-    return UINT32_MAX;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain);
-
-
-RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
-{
-    NOREF(hThreadCtx);
+    NOREF(phCtxHook);
     NOREF(pfnCallback);
     NOREF(pvUser);
     return VERR_NOT_SUPPORTED;
 }
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
+RT_EXPORT_SYMBOL(RTThreadCtxHookCreate);
 
 
-RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
+RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook)
 {
-    NOREF(hThreadCtx);
+    return hCtxHook == NIL_RTTHREADCTXHOOK ? VINF_SUCCESS : VERR_INVALID_HANDLE;
+}
+RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy);
+
+
+RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
+{
+    NOREF(hCtxHook);
     return VERR_NOT_SUPPORTED;
 }
-RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
+RT_EXPORT_SYMBOL(RTThreadCtxHookEnable);
 
 
-RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
+RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
 {
-    NOREF(hThreadCtx);
+    NOREF(hCtxHook);
+    return VERR_NOT_SUPPORTED;
+}
+RT_EXPORT_SYMBOL(RTThreadCtxHookDisable);
+
+
+RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
+{
+    NOREF(hCtxHook);
     return false;
 }
-RT_EXPORT_SYMBOL(RTThreadCtxHooksAreRegistered);
+RT_EXPORT_SYMBOL(RTThreadCtxHookIsEnabled);
 
Index: /trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c	(revision 55862)
+++ /trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c	(revision 55863)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /** @file
- * IPRT - Thread-Context Hook, Ring-0 Driver, Linux.
+ * IPRT - Thread Context Switching Hook, Ring-0 Driver, Linux.
  */
 
@@ -42,6 +42,7 @@
 #include "internal/thread.h"
 
+
 /*
- * Linux kernel 2.6.23 introduced thread-context hooks but RedHat 2.6.18 kernels
+ * Linux kernel 2.6.23 introduced preemption notifiers but RedHat 2.6.18 kernels
  * got it backported.
  */
@@ -52,24 +53,23 @@
 *******************************************************************************/
 /**
- * The internal thread-context object.
- */
-typedef struct RTTHREADCTXINT
-{
-    /** Magic value (RTTHREADCTXINT_MAGIC). */
+ * The internal hook object for linux.
+ */
+typedef struct RTTHREADCTXHOOKINT
+{
+    /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */
     uint32_t volatile           u32Magic;
-    /** The thread handle (owner) for which the context-hooks are registered. */
+    /** The thread handle (owner) for which the hook is registered. */
     RTNATIVETHREAD              hOwner;
     /** The preemption notifier object. */
-    struct preempt_notifier     hPreemptNotifier;
-    /** Whether this handle has any hooks registered or not. */
-    bool                        fRegistered;
-    /** Pointer to the registered thread-context hook. */
-    PFNRTTHREADCTXHOOK          pfnThreadCtxHook;
-    /** User argument passed to the thread-context hook. */
+    struct preempt_notifier     LnxPreemptNotifier;
+    /** Whether the hook is enabled or not.  If enabled, the LnxPreemptNotifier
+     * is linked into the owning thread's list of preemption callouts. */
+    bool                        fEnabled;
+    /** Pointer to the user callback. */
+    PFNRTTHREADCTXHOOK          pfnCallback;
+    /** User argument passed to the callback. */
     void                       *pvUser;
-    /** The thread-context operations. */
-    struct preempt_ops          hPreemptOps;
-    /** The reference count for this object. */
-    uint32_t volatile           cRefs;
+    /** The linux callbacks. */
+    struct preempt_ops          PreemptOps;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 19) && defined(RT_ARCH_AMD64)
     /** Starting with 3.1.19, the linux kernel doesn't restore kernel RFLAGS during
@@ -77,13 +77,14 @@
     RTCCUINTREG                 fSavedRFlags;
 #endif
-} RTTHREADCTXINT, *PRTTHREADCTXINT;
+} RTTHREADCTXHOOKINT;
+typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT;
 
 
 /**
- * Hook function for the thread-preempting event.
+ * Hook function for the thread schedule out event.
  *
  * @param   pPreemptNotifier    Pointer to the preempt_notifier struct.
- * @param   pNext               Pointer to the task that is preempting the
- *                              current thread.
+ * @param   pNext               Pointer to the task that is being scheduled
+ *                              instead of the current thread.
  *
  * @remarks Called with the rq (runqueue) lock held and with preemption and
@@ -92,5 +93,5 @@
 static void rtThreadCtxHooksLnxSchedOut(struct preempt_notifier *pPreemptNotifier, struct task_struct *pNext)
 {
-    PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
+    PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier);
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     RTCCUINTREG fSavedEFlags = ASMGetFlags();
@@ -99,9 +100,9 @@
 
     AssertPtr(pThis);
-    AssertPtr(pThis->pfnThreadCtxHook);
-    Assert(pThis->fRegistered);
+    AssertPtr(pThis->pfnCallback);
+    Assert(pThis->fEnabled);
     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
 
-    pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
+    pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser);
 
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
@@ -115,15 +116,16 @@
 
 /**
- * Hook function for the thread-resumed event.
+ * Hook function for the thread schedule in event.
  *
  * @param   pPreemptNotifier    Pointer to the preempt_notifier struct.
- * @param   iCpu                The CPU this thread is scheduled on.
+ * @param   iCpu                The CPU this thread is being scheduled on.
  *
  * @remarks Called without holding the rq (runqueue) lock and with preemption
  *          enabled!
+ * @todo    r=bird: Preemption is of course disabled when it is called.
  */
 static void rtThreadCtxHooksLnxSchedIn(struct preempt_notifier *pPreemptNotifier, int iCpu)
 {
-    PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
+    PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier);
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     RTCCUINTREG fSavedEFlags = ASMGetFlags();
@@ -132,8 +134,8 @@
 
     AssertPtr(pThis);
-    AssertPtr(pThis->pfnThreadCtxHook);
-    Assert(pThis->fRegistered);
-
-    pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
+    AssertPtr(pThis->pfnCallback);
+    Assert(pThis->fEnabled);
+
+    pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser);
 
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
@@ -152,212 +154,150 @@
  * @param   pThis   Pointer to the internal thread-context object.
  */
-DECLINLINE(void) rtThreadCtxHooksDeregister(PRTTHREADCTXINT pThis)
-{
-    preempt_notifier_unregister(&pThis->hPreemptNotifier);
-    pThis->hPreemptOps.sched_out = NULL;
-    pThis->hPreemptOps.sched_in  = NULL;
-    pThis->fRegistered           = false;
-}
-
-
-RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
-{
-    PRTTHREADCTXINT pThis;
+DECLINLINE(void) rtThreadCtxHookDisable(PRTTHREADCTXHOOKINT pThis)
+{
+    Assert(pThis->PreemptOps.sched_out == rtThreadCtxHooksLnxSchedOut);
+    Assert(pThis->PreemptOps.sched_in  == rtThreadCtxHooksLnxSchedIn);
+    preempt_disable();
+    preempt_notifier_unregister(&pThis->LnxPreemptNotifier);
+    pThis->fEnabled = false;
+    preempt_enable();
+}
+
+
+RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXHOOKINT pThis;
     Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis));
+    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
+    AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
+
+    /*
+     * Allocate and initialize a new hook.  We don't register it yet, just
+     * create it.
+     */
+    pThis = (PRTTHREADCTXHOOKINT)RTMemAllocZ(sizeof(*pThis));
     if (RT_UNLIKELY(!pThis))
         return VERR_NO_MEMORY;
-    pThis->u32Magic    = RTTHREADCTXINT_MAGIC;
-    pThis->hOwner      = RTThreadNativeSelf();
-    pThis->fRegistered = false;
-    preempt_notifier_init(&pThis->hPreemptNotifier, &pThis->hPreemptOps);
-    pThis->cRefs       = 1;
-
-    *phThreadCtx = pThis;
+    pThis->u32Magic     = RTTHREADCTXHOOKINT_MAGIC;
+    pThis->hOwner       = RTThreadNativeSelf();
+    pThis->fEnabled     = false;
+    pThis->pfnCallback  = pfnCallback;
+    pThis->pvUser       = pvUser;
+    preempt_notifier_init(&pThis->LnxPreemptNotifier, &pThis->PreemptOps);
+    pThis->PreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut;
+    pThis->PreemptOps.sched_in  = rtThreadCtxHooksLnxSchedIn;
+
+    *phCtxHook = pThis;
     return VINF_SUCCESS;
 }
-RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
-{
-    /*
-     * Validate input.
-     */
-    uint32_t        cRefs;
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    AssertPtr(pThis);
-    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
-                    UINT32_MAX);
-
-    cRefs = ASMAtomicIncU32(&pThis->cRefs);
-    Assert(cRefs < UINT32_MAX / 2);
-    return cRefs;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain);
-
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
-{
-    /*
-     * Validate input.
-     */
-    uint32_t        cRefs;
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
-        return 0;
-
-    AssertPtr(pThis);
-    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
-                    UINT32_MAX);
+RT_EXPORT_SYMBOL(RTThreadCtxHookCreate);
+
+
+RTDECL(int ) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    if (pThis == NIL_RTTHREADCTXHOOK)
+        return VINF_SUCCESS;
+    AssertPtr(pThis);
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                    VERR_INVALID_HANDLE);
     Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    cRefs = ASMAtomicDecU32(&pThis->cRefs);
-    if (!cRefs)
+    Assert(pThis->fEnabled || pThis->hOwner == RTThreadNativeSelf());
+
+    /*
+     * If there's still a registered thread-context hook, deregister it now before destroying the object.
+     */
+    if (pThis->fEnabled)
     {
-        /*
-         * If there's still a registered thread-context hook, deregister it now before destroying the object.
-         */
-        if (pThis->fRegistered)
-            rtThreadCtxHooksDeregister(pThis);
-
-        /*
-         * Paranoia... but since these are ring-0 threads we can't be too careful.
-         */
-        Assert(!pThis->fRegistered);
-        Assert(!pThis->hPreemptOps.sched_out);
-        Assert(!pThis->hPreemptOps.sched_in);
-
-        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
-        RTMemFree(pThis);
+        Assert(pThis->hOwner == RTThreadNativeSelf());
+        rtThreadCtxHookDisable(pThis);
+        Assert(!pThis->fEnabled); /* paranoia */
     }
-    else
-        Assert(cRefs < UINT32_MAX / 2);
-
-    return cRefs;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease);
-
-
-RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
-{
-    /*
-     * Validate input.
-     */
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
-        return VERR_INVALID_HANDLE;
-    AssertPtr(pThis);
-    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+
+    ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
+    RTMemFree(pThis);
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy);
+
+
+RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    AssertPtr(pThis);
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
                     VERR_INVALID_HANDLE);
     Assert(pThis->hOwner == RTThreadNativeSelf());
-    Assert(!pThis->hPreemptOps.sched_out);
-    Assert(!pThis->hPreemptOps.sched_in);
-
-    /*
-     * Register the callback.
-     */
-    pThis->hPreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut;
-    pThis->hPreemptOps.sched_in  = rtThreadCtxHooksLnxSchedIn;
-    pThis->pvUser                = pvUser;
-    pThis->pfnThreadCtxHook      = pfnThreadCtxHook;
-    pThis->fRegistered           = true;
-    preempt_notifier_register(&pThis->hPreemptNotifier);
+    Assert(!pThis->fEnabled);
+    if (!pThis->fEnabled)
+    {
+        Assert(pThis->PreemptOps.sched_out == rtThreadCtxHooksLnxSchedOut);
+        Assert(pThis->PreemptOps.sched_in == rtThreadCtxHooksLnxSchedIn);
+
+        /*
+         * Register the callback.
+         */
+        preempt_disable();
+        pThis->fEnabled = true;
+        preempt_notifier_register(&pThis->LnxPreemptNotifier);
+        preempt_enable();
+    }
 
     return VINF_SUCCESS;
 }
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
-
-
-RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
-{
-    /*
-     * Validate input.
-     */
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
-        return VERR_INVALID_HANDLE;
-    AssertPtr(pThis);
-    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
-                    VERR_INVALID_HANDLE);
-    Assert(pThis->hOwner == RTThreadNativeSelf());
-    Assert(pThis->fRegistered);
-
-    /*
-     * Deregister the callback.
-     */
-    rtThreadCtxHooksDeregister(pThis);
+RT_EXPORT_SYMBOL(RTThreadCtxHookEnable);
+
+
+RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    if (pThis != NIL_RTTHREADCTXHOOK)
+    {
+        AssertPtr(pThis);
+        AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                        VERR_INVALID_HANDLE);
+        Assert(pThis->hOwner == RTThreadNativeSelf());
+
+        /*
+         * Deregister the callback.
+         */
+        if (pThis->fEnabled)
+            rtThreadCtxHookDisable(pThis);
+    }
     return VINF_SUCCESS;
 }
-RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
-
-
-RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
-{
-    /*
-     * Validate input.
-     */
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
+RT_EXPORT_SYMBOL(RTThreadCtxHookDisable);
+
+
+RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    if (pThis == NIL_RTTHREADCTXHOOK)
         return false;
     AssertPtr(pThis);
-    AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
-
-    return pThis->fRegistered;
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                    false);
+
+    return pThis->fEnabled;
 }
 
 #else    /* Not supported / Not needed */
-
-RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
-{
-    NOREF(phThreadCtx);
-    return VERR_NOT_SUPPORTED;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
-{
-    NOREF(hThreadCtx);
-    return UINT32_MAX;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain);
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
-{
-    NOREF(hThreadCtx);
-    return UINT32_MAX;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease);
-
-
-RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
-{
-    NOREF(hThreadCtx);
-    NOREF(pfnThreadCtxHook);
-    NOREF(pvUser);
-    return VERR_NOT_SUPPORTED;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
-
-
-RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
-{
-    NOREF(hThreadCtx);
-    return VERR_NOT_SUPPORTED;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
-
-
-RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
-{
-    NOREF(hThreadCtx);
-    return false;
-}
-RT_EXPORT_SYMBOL(RTThreadCtxHooksAreRegistered);
-
+# include "../generic/threadctxhooks-r0drv-generic.cpp"
 #endif   /* Not supported / Not needed */
 
Index: /trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c	(revision 55862)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c	(revision 55863)
@@ -1,9 +1,9 @@
 /* $Id$ */
 /** @file
- * IPRT - Thread-Context Hook, Ring-0 Driver, Solaris.
+ * IPRT - Thread Context Switching Hook, Ring-0 Driver, Solaris.
  */
 
 /*
- * Copyright (C) 2013 Oracle Corporation
+ * Copyright (C) 2013-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -45,21 +45,22 @@
 *******************************************************************************/
 /**
- * The internal thread-context object.
- */
-typedef struct RTTHREADCTXINT
-{
-    /** Magic value (RTTHREADCTXINT_MAGIC). */
+ * The internal hook object for solaris.
+ */
+typedef struct RTTHREADCTXHOOKINT
+{
+    /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */
     uint32_t volatile           u32Magic;
     /** The thread handle (owner) for which the context-hooks are registered. */
     RTNATIVETHREAD              hOwner;
-    /** Pointer to the registered thread-context hook. */
-    PFNRTTHREADCTXHOOK          pfnThreadCtxHook;
-    /** User argument passed to the thread-context hook. */
+    /** Pointer to the registered callback function. */
+    PFNRTTHREADCTXHOOK          pfnCallback;
+    /** User argument passed to the callback function. */
     void                       *pvUser;
-    /** Whether this handle has any hooks registered or not. */
-    bool volatile               fRegistered;
+    /** Whether the hook is enabled or not. */
+    bool volatile               fEnabled;
     /** Number of references to this object. */
     uint32_t volatile           cRefs;
-} RTTHREADCTXINT, *PRTTHREADCTXINT;
+} RTTHREADCTXHOOKINT;
+typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT;
 
 
@@ -67,9 +68,9 @@
 *   Defined Constants And Macros                                               *
 *******************************************************************************/
-/** Validates a thread-context hook handle and returns rc if not valid. */
+/** Validates a hook handle and returns rc if not valid. */
 #define RTTHREADCTX_VALID_RETURN_RC(pThis, rc) \
     do { \
         AssertPtrReturn((pThis), (rc)); \
-        AssertReturn((pThis)->u32Magic == RTTHREADCTXINT_MAGIC, (rc)); \
+        AssertReturn((pThis)->u32Magic == RTTHREADCTXHOOKINT_MAGIC, (rc)); \
         AssertReturn((pThis)->cRefs > 0, (rc)); \
     } while (0)
@@ -77,21 +78,21 @@
 
 /**
- * Hook function for the thread-preempting event.
- *
- * @param   pvThreadCtxInt  Opaque pointer to the internal thread-context
- *                          object.
+ * Hook function for the thread-save event.
+ *
+ * @param   pvThreadCtxInt  Opaque pointer to the internal hook object.
  *
  * @remarks Called with the with preemption disabled!
  */
-static void rtThreadCtxHooksSolPreempting(void *pvThreadCtxInt)
-{
-    PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
+static void rtThreadCtxHookSolOut(void *pvThreadCtxInt)
+{
+    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
     AssertPtr(pThis);
     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    if (pThis->fRegistered)
-    {
-        Assert(pThis->pfnThreadCtxHook);
-        pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
+    Assert(pThis->cRefs > 0);
+
+    if (pThis->fEnabled)
+    {
+        Assert(pThis->pfnCallback);
+        pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser);
     }
 }
@@ -99,19 +100,19 @@
 
 /**
- * Hook function for the thread-resumed event.
- *
- * @param   pvThreadCtxInt  Opaque pointer to the internal thread-context
- *                          object.
- */
-static void rtThreadCtxHooksSolResumed(void *pvThreadCtxInt)
-{
-    PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
+ * Hook function for the thread-restore event.
+ *
+ * @param   pvThreadCtxInt  Opaque pointer to the internal hook object.
+ */
+static void rtThreadCtxHookSolIn(void *pvThreadCtxInt)
+{
+    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
     AssertPtr(pThis);
     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    if (pThis->fRegistered)
-    {
-        Assert(pThis->pfnThreadCtxHook);
-        pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
+    Assert(pThis->cRefs > 0);
+
+    if (pThis->fEnabled)
+    {
+        Assert(pThis->pfnCallback);
+        pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser);
     }
 }
@@ -121,48 +122,61 @@
  * Hook function for the thread-free event.
  *
- * @param   pvThreadCtxInt      Opaque pointer to the internal thread-context
- *                              object.
+ * This is used for making sure the hook object is safely released - see
+ * RTThreadCtxHookRelease for details.
+ *
+ * @param   pvThreadCtxInt      Opaque pointer to the internal hook object.
  * @param   fIsExec             Whether this event is triggered due to exec().
  */
-static void rtThreadCtxHooksSolFree(void *pvThreadCtxInt, int fIsExec)
-{
-    PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
+static void rtThreadCtxHookSolFree(void *pvThreadCtxInt, int fIsExec)
+{
+    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
     AssertPtrReturnVoid(pThis);
-    AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
+    AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
 
     uint32_t cRefs = ASMAtomicReadU32(&pThis->cRefs);
-    if (RT_UNLIKELY(!cRefs))
+    if (cRefs > 0)
+    {
+        cRefs = ASMAtomicDecU32(&pThis->cRefs);
+        if (!cRefs)
+        {
+            Assert(!pThis->fEnabled);
+            ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
+            RTMemFree(pThis);
+        }
+    }
+    else
     {
         /* Should never happen. */
-        AssertMsgFailed(("rtThreadCtxHooksSolFree with cRefs=0 pThis=%p\n", pThis));
-        return;
-    }
-
-    cRefs = ASMAtomicDecU32(&pThis->cRefs);
-    if (!cRefs)
-    {
-        Assert(!pThis->fRegistered);
-        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
-        RTMemFree(pThis);
-    }
-}
-
-
-RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
-{
-    PRTTHREADCTXINT pThis;
+        AssertMsgFailed(("rtThreadCtxHookSolFree with cRefs=0 pThis=%p\n", pThis));
+    }
+}
+
+
+RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXHOOKINT pThis;
     Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis));
+    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
+    AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
+
+    /*
+     * Allocate and initialize a new hook.
+     */
+    pThis = (PRTTHREADCTXHOOKINT)RTMemAllocZ(sizeof(*pThis));
     if (RT_UNLIKELY(!pThis))
         return VERR_NO_MEMORY;
-    pThis->u32Magic    = RTTHREADCTXINT_MAGIC;
-    pThis->hOwner      = RTThreadNativeSelf();
-    pThis->fRegistered = false;
-    pThis->cRefs       = 2;               /* One reference for the thread, one for the hook object. */
-
-    /*
-     * installctx() allocates memory and thus cannot be used in RTThreadCtxHooksRegister() which can be used
-     * with preemption disabled. We allocate the context-hooks here and use 'fRegistered' to determine if we can
+    pThis->u32Magic     = RTTHREADCTXHOOKINT_MAGIC;
+    pThis->hOwner       = RTThreadNativeSelf();
+    pThis->pfnCallback  = pfnCallback;
+    pThis->pvUser       = pvUser;
+    pThis->fEnabled     = false;
+    pThis->cRefs        = 2;        /* One reference for the thread, one for the caller. */
+
+    /*
+     * installctx() allocates memory and thus cannot be used in RTThreadCtxHookRegister() which can be used
+     * with preemption disabled. We allocate the context-hooks here and use 'fEnabled' to determine if we can
      * invoke the consumer's hook or not.
      */
@@ -171,9 +185,9 @@
         g_rtSolThreadCtx.Install.pfnSol_installctx_old(curthread,
                                                        pThis,
-                                                       rtThreadCtxHooksSolPreempting,
-                                                       rtThreadCtxHooksSolResumed,
-                                                       NULL,                          /* fork */
-                                                       NULL,                          /* lwp_create */
-                                                       rtThreadCtxHooksSolFree);
+                                                       rtThreadCtxHookSolOut,   /* save */
+                                                       rtThreadCtxHookSolIn,    /* restore */
+                                                       NULL,                    /* fork */
+                                                       NULL,                    /* lwp_create */
+                                                       rtThreadCtxHookSolFree);
     }
     else
@@ -181,52 +195,50 @@
         g_rtSolThreadCtx.Install.pfnSol_installctx(curthread,
                                                    pThis,
-                                                   rtThreadCtxHooksSolPreempting,
-                                                   rtThreadCtxHooksSolResumed,
-                                                   NULL,                              /* fork */
-                                                   NULL,                              /* lwp_create */
-                                                   NULL,                              /* exit */
-                                                   rtThreadCtxHooksSolFree);
-    }
-
-    *phThreadCtx = pThis;
+                                                   rtThreadCtxHookSolOut,       /* save */
+                                                   rtThreadCtxHookSolIn,        /* restore */
+                                                   NULL,                        /* fork */
+                                                   NULL,                        /* lwp_create */
+                                                   NULL,                        /* exit */
+                                                   rtThreadCtxHookSolFree);
+    }
+
+    *phCtxHook = pThis;
     return VINF_SUCCESS;
 }
 
 
-RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
-{
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX);
-
-    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
-    Assert(cRefs < UINT32_MAX / 2);
-    return cRefs;
-}
-
-
-RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
-{
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
-        return 0;
-
-    RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX);
+RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook)
+{
+    /*
+     * Validate input, ignoring NIL.
+     */
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    if (pThis == NIL_RTTHREADCTXHOOK)
+        return VINF_SUCCESS;
+    RTTHREADCTX_VALID_RETURN_RC(hCtxHook, VERR_INVALID_HANDLE);
     Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    ASMAtomicWriteBool(&pThis->fRegistered, false);
+    Assert(pThis->fEnabled || pThis->hOwner == RTThreadNativeSelf());
+
+    /*
+     * Make sure it's disabled.
+     */
+    ASMAtomicWriteBool(&pThis->fEnabled, false);
+
+    /*
+     * Decrement.
+     */
     uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
-
     if (   cRefs == 1
         && pThis->hOwner == RTThreadNativeSelf())
     {
         /*
-         * removectx() will invoke rtThreadCtxHooksSolFree() and there is no way to bypass it and still use
-         * rtThreadCtxHooksSolFree() at the same time.  Hence the convulated reference counting.
+         * removectx() will invoke rtThreadCtxHookSolFree() and there is no way to bypass it and still use
+         * rtThreadCtxHookSolFree() at the same time.  Hence the convulated reference counting.
          *
          * When this function is called from the owner thread and is the last reference, we call removectx() which
-         * will invoke rtThreadCtxHooksSolFree() with cRefs = 1 and that will then free the hook object.
+         * will invoke rtThreadCtxHookSolFree() with cRefs = 1 and that will then free the hook object.
          *
          * When the function is called from a different thread, we simply decrement the reference. Whenever the
-         * ring-0 thread dies, Solaris will call rtThreadCtxHooksSolFree() which will free the hook object.
+         * ring-0 thread dies, Solaris will call rtThreadCtxHookSolFree() which will free the hook object.
          */
         int rc;
@@ -235,9 +247,9 @@
             rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread,
                                                               pThis,
-                                                              rtThreadCtxHooksSolPreempting,
-                                                              rtThreadCtxHooksSolResumed,
-                                                              NULL,                          /* fork */
-                                                              NULL,                          /* lwp_create */
-                                                              rtThreadCtxHooksSolFree);
+                                                              rtThreadCtxHookSolOut,    /* save */
+                                                              rtThreadCtxHookSolIn,     /* restore */
+                                                              NULL,                     /* fork */
+                                                              NULL,                     /* lwp_create */
+                                                              rtThreadCtxHookSolFree);
         }
         else
@@ -245,10 +257,10 @@
             rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread,
                                                           pThis,
-                                                          rtThreadCtxHooksSolPreempting,
-                                                          rtThreadCtxHooksSolResumed,
-                                                          NULL,                              /* fork */
-                                                          NULL,                              /* lwp_create */
-                                                          NULL,                              /* exit */
-                                                          rtThreadCtxHooksSolFree);
+                                                          rtThreadCtxHookSolOut,        /* save */
+                                                          rtThreadCtxHookSolIn,         /* restore */
+                                                          NULL,                         /* fork */
+                                                          NULL,                         /* lwp_create */
+                                                          NULL,                         /* exit */
+                                                          rtThreadCtxHookSolFree);
         }
         AssertMsg(rc, ("removectx() failed. rc=%d\n", rc));
@@ -267,5 +279,5 @@
          */
         Assert(pThis->hOwner != RTThreadNativeSelf());
-        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
+        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
         RTMemFree(pThis);
     }
@@ -275,23 +287,20 @@
 
 
-RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
+RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
 {
     /*
      * Validate input.
      */
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
-        return VERR_INVALID_HANDLE;
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     AssertPtr(pThis);
-    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
                     VERR_INVALID_HANDLE);
     Assert(pThis->hOwner == RTThreadNativeSelf());
-
-    /*
-     * Register the callback.
-     */
-    pThis->pvUser           = pvUser;
-    pThis->pfnThreadCtxHook = pfnThreadCtxHook;
-    pThis->fRegistered      = true;
+    Assert(!pThis->fEnabled);
+
+    /*
+     * Mark it as enabled.
+     */
+    pThis->fEnabled = true;
 
     return VINF_SUCCESS;
@@ -299,22 +308,22 @@
 
 
-RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
+RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
 {
     /*
      * Validate input.
      */
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
-        return VERR_INVALID_HANDLE;
-    AssertPtr(pThis);
-    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
-                    VERR_INVALID_HANDLE);
-    Assert(pThis->hOwner == RTThreadNativeSelf());
-    Assert(pThis->fRegistered);
-
-    /*
-     * Deregister the callback.
-     */
-    pThis->fRegistered = false;
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    if (pThis != NIL_RTTHREADCTXHOOK)
+    {
+        AssertPtr(pThis);
+        AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                        VERR_INVALID_HANDLE);
+        Assert(pThis->hOwner == RTThreadNativeSelf());
+
+        /*
+         * Mark it as disabled.
+         */
+        pThis->fEnabled = false;
+    }
 
     return VINF_SUCCESS;
@@ -322,16 +331,17 @@
 
 
-RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
+RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
 {
     /*
      * Validate input.
      */
-    PRTTHREADCTXINT pThis = hThreadCtx;
-    if (pThis == NIL_RTTHREADCTX)
+    PRTTHREADCTXHOOKINT pThis = hCtxHook;
+    if (pThis == NIL_RTTHREADCTXHOOK)
         return false;
     AssertPtr(pThis);
-    AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
-
-    return pThis->fRegistered;
-}
-
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                    false);
+
+    return pThis->fEnabled;
+}
+
Index: /trunk/src/VBox/Runtime/testcase/tstRTR0ThreadPreemption.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTR0ThreadPreemption.cpp	(revision 55862)
+++ /trunk/src/VBox/Runtime/testcase/tstRTR0ThreadPreemption.cpp	(revision 55863)
@@ -49,5 +49,4 @@
     RTCPUID             uSourceCpuId;
     RTNATIVETHREAD      hSourceThread;
-    RTTHREADCTX         hThreadCtx;
 
     /* For RTTHREADCTXEVENT_PREEMPTING. */
@@ -82,5 +81,5 @@
     switch (enmEvent)
     {
-        case RTTHREADCTXEVENT_PREEMPTING:
+        case RTTHREADCTXEVENT_OUT:
         {
             ASMAtomicWriteBool(&pData->fPreemptingInvoked, true);
@@ -119,5 +118,5 @@
         }
 
-        case RTTHREADCTXEVENT_RESUMED:
+        case RTTHREADCTXEVENT_IN:
         {
             ASMAtomicWriteBool(&pData->fResumedInvoked, true);
@@ -302,27 +301,8 @@
             }
 
-            bool fRegistered = RTThreadCtxHooksAreRegistered(NIL_RTTHREADCTX);
+            bool fRegistered = RTThreadCtxHookIsEnabled(NIL_RTTHREADCTXHOOK);
             if (fRegistered)
             {
-                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered returns true before creating any hooks");
-                break;
-            }
-
-            RTTHREADCTX hThreadCtx;
-            int rc = RTThreadCtxHooksCreate(&hThreadCtx);
-            if (RT_FAILURE(rc))
-            {
-                if (rc == VERR_NOT_SUPPORTED)
-                    RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED");
-                else
-                    RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc);
-                break;
-            }
-
-            fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
-            if (fRegistered)
-            {
-                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered returns true before registering any hooks");
-                RTThreadCtxHooksRelease(hThreadCtx);
+                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled returns true before creating any hooks");
                 break;
             }
@@ -331,5 +311,4 @@
             AssertReturn(pCtxData, VERR_NO_MEMORY);
             pCtxData->u32Magic           = TSTRTR0THREADCTXDATA_MAGIC;
-            pCtxData->hThreadCtx         = hThreadCtx;
             pCtxData->fPreemptingSuccess = false;
             pCtxData->fPreemptingInvoked = false;
@@ -339,4 +318,24 @@
             RT_ZERO(pCtxData->achResult);
 
+            RTTHREADCTXHOOK hThreadCtx;
+            int rc = RTThreadCtxHookCreate(&hThreadCtx, 0, tstRTR0ThreadCtxHook, pCtxData);
+            if (RT_FAILURE(rc))
+            {
+                if (rc == VERR_NOT_SUPPORTED)
+                    RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED");
+                else
+                    RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc);
+                RTMemFree(pCtxData);
+                break;
+            }
+
+            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
+            if (fRegistered)
+            {
+                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled returns true before registering any hooks");
+                RTThreadCtxHookDestroy(hThreadCtx);
+                break;
+            }
+
             RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
             RTThreadPreemptDisable(&PreemptState);
@@ -345,19 +344,19 @@
             pCtxData->uSourceCpuId       = RTMpCpuId();
 
-            rc = RTThreadCtxHooksRegister(hThreadCtx, &tstRTR0ThreadCtxHook, pCtxData);
+            rc = RTThreadCtxHookEnable(hThreadCtx);
             if (RT_FAILURE(rc))
             {
                 RTThreadPreemptRestore(&PreemptState);
                 RTMemFree(pCtxData);
-                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRegister returns %Rrc", rc);
-                break;
-            }
-
-            fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
+                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookEnable returns %Rrc", rc);
+                break;
+            }
+
+            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
             if (!fRegistered)
             {
                 RTThreadPreemptRestore(&PreemptState);
                 RTMemFree(pCtxData);
-                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered return false when hooks are supposedly registered");
+                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return false when hooks are supposedly registered");
                 break;
             }
@@ -428,18 +427,18 @@
             }
 
-            RTThreadCtxHooksDeregister(hThreadCtx);
-
-            fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
+            RTThreadCtxHookDisable(hThreadCtx);
+
+            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
             if (fRegistered)
             {
                 RTMemFree(pCtxData);
-                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered return true when hooks are deregistered");
+                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return true when hooks are deregistered");
                 break;
             }
 
             Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-            uint32_t cRefs = RTThreadCtxHooksRelease(hThreadCtx);
-            if (cRefs == UINT32_MAX)
-                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns invalid cRefs!");
+            rc = RTThreadCtxHookDestroy(hThreadCtx);
+            if (RT_FAILURE(rc))
+                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns %Rrc!", rc);
 
             RTMemFree(pCtxData);
Index: /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp	(revision 55862)
+++ /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp	(revision 55863)
@@ -889,5 +889,5 @@
                                         pGVMM->cEMTs += cCpus;
 
-                                        rc = VMMR0ThreadCtxHooksCreate(&pVM->aCpus[0]);
+                                        rc = VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[0]);
                                         if (RT_SUCCESS(rc))
                                         {
@@ -1123,5 +1123,5 @@
              *        solution for not deregistering hooks everytime we're leaving HMR0
              *        context. */
-            VMMR0ThreadCtxHooksRelease(&pVM->aCpus[idCpu]);
+            VMMR0ThreadCtxHookDestroyForEmt(&pVM->aCpus[idCpu]);
         }
 
@@ -1351,6 +1351,5 @@
     pVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf();
 
-    rc = VMMR0ThreadCtxHooksCreate(&pVM->aCpus[idCpu]);
-    return rc;
+    return VMMR0ThreadCtxHookCreateForEmt(&pVM->aCpus[idCpu]);
 }
 
Index: /trunk/src/VBox/VMM/VMMR0/HMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMR0.cpp	(revision 55862)
+++ /trunk/src/VBox/VMM/VMMR0/HMR0.cpp	(revision 55863)
@@ -1366,5 +1366,5 @@
 
 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
-    AssertReturn(!VMMR0ThreadCtxHooksAreRegistered(pVCpu), VERR_HM_IPE_5);
+    AssertReturn(!VMMR0ThreadCtxHookIsEnabled(pVCpu), VERR_HM_IPE_5);
     bool fStartedSet = PGMR0DynMapStartOrMigrateAutoSet(pVCpu);
 #endif
@@ -1471,5 +1471,5 @@
 
 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
-    AssertReturn(!VMMR0ThreadCtxHooksAreRegistered(pVCpu), VERR_HM_IPE_4);
+    AssertReturn(!VMMR0ThreadCtxHookIsEnabled(pVCpu), VERR_HM_IPE_4);
     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     PGMRZDynMapStartAutoSet(pVCpu);
Index: /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 55862)
+++ /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 55863)
@@ -121,10 +121,10 @@
 
 /** Assert that preemption is disabled or covered by thread-context hooks. */
-#define HMSVM_ASSERT_PREEMPT_SAFE()           Assert(   VMMR0ThreadCtxHooksAreRegistered(pVCpu) \
+#define HMSVM_ASSERT_PREEMPT_SAFE()           Assert(   VMMR0ThreadCtxHookIsEnabled(pVCpu) \
                                                      || !RTThreadPreemptIsEnabled(NIL_RTTHREAD));
 
 /** Assert that we haven't migrated CPUs when thread-context hooks are not
  *  used. */
-#define HMSVM_ASSERT_CPU_SAFE()               AssertMsg(   VMMR0ThreadCtxHooksAreRegistered(pVCpu) \
+#define HMSVM_ASSERT_CPU_SAFE()               AssertMsg(   VMMR0ThreadCtxHookIsEnabled(pVCpu) \
                                                         || pVCpu->hm.s.idEnteredCpu == RTMpCpuId(), \
                                                         ("Illegal migration! Entered on CPU %u Current %u\n", \
@@ -1741,8 +1741,8 @@
     switch (enmEvent)
     {
-        case RTTHREADCTXEVENT_PREEMPTING:
+        case RTTHREADCTXEVENT_OUT:
         {
             Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-            Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
+            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
             VMCPU_ASSERT_EMT(pVCpu);
 
@@ -1769,8 +1769,8 @@
         }
 
-        case RTTHREADCTXEVENT_RESUMED:
+        case RTTHREADCTXEVENT_IN:
         {
             Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-            Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
+            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
             VMCPU_ASSERT_EMT(pVCpu);
 
@@ -2140,6 +2140,7 @@
      */
 
+    /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
     /* Deregister hook now that we've left HM context before re-enabling preemption. */
-    VMMR0ThreadCtxHooksDeregister(pVCpu);
+    VMMR0ThreadCtxHookDisable(pVCpu);
 
     /* Leave HM context. This takes care of local init (term). */
@@ -2198,5 +2199,6 @@
 
         /* Deregister the hook now that we've left HM context before re-enabling preemption. */
-        VMMR0ThreadCtxHooksDeregister(pVCpu);
+        /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
+        VMMR0ThreadCtxHookDisable(pVCpu);
 
         /* Leave HM context. This takes care of local init (term). */
Index: /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 55862)
+++ /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 55863)
@@ -184,10 +184,10 @@
 
 /** Assert that preemption is disabled or covered by thread-context hooks. */
-#define HMVMX_ASSERT_PREEMPT_SAFE()       Assert(   VMMR0ThreadCtxHooksAreRegistered(pVCpu)   \
+#define HMVMX_ASSERT_PREEMPT_SAFE()       Assert(   VMMR0ThreadCtxHookIsEnabled(pVCpu)   \
                                                  || !RTThreadPreemptIsEnabled(NIL_RTTHREAD));
 
 /** Assert that we haven't migrated CPUs when thread-context hooks are not
  *  used. */
-#define HMVMX_ASSERT_CPU_SAFE()           AssertMsg(   VMMR0ThreadCtxHooksAreRegistered(pVCpu) \
+#define HMVMX_ASSERT_CPU_SAFE()           AssertMsg(   VMMR0ThreadCtxHookIsEnabled(pVCpu) \
                                                     || pVCpu->hm.s.idEnteredCpu == RTMpCpuId(), \
                                                     ("Illegal migration! Entered on CPU %u Current %u\n", \
@@ -7243,5 +7243,6 @@
     /** @todo Deregistering here means we need to VMCLEAR always
      *        (longjmp/exit-to-r3) in VT-x which is not efficient. */
-    VMMR0ThreadCtxHooksDeregister(pVCpu);
+    /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
+    VMMR0ThreadCtxHookDisable(pVCpu);
 
     /* Leave HM context. This takes care of local init (term). */
@@ -7376,7 +7377,7 @@
          * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
          */
-        RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; \
         VMMRZCallRing3RemoveNotification(pVCpu);
         VMMRZCallRing3Disable(pVCpu);
+        RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
         RTThreadPreemptDisable(&PreemptState);
 
@@ -7408,5 +7409,6 @@
         }
 
-        VMMR0ThreadCtxHooksDeregister(pVCpu);
+        /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here!  */
+        VMMR0ThreadCtxHookDisable(pVCpu);
         HMR0LeaveCpu(pVCpu);
         RTThreadPreemptRestore(&PreemptState);
@@ -8222,8 +8224,8 @@
     switch (enmEvent)
     {
-        case RTTHREADCTXEVENT_PREEMPTING:
+        case RTTHREADCTXEVENT_OUT:
         {
             Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-            Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
+            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
             VMCPU_ASSERT_EMT(pVCpu);
 
@@ -8256,8 +8258,8 @@
         }
 
-        case RTTHREADCTXEVENT_RESUMED:
+        case RTTHREADCTXEVENT_IN:
         {
             Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-            Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu));
+            Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
             VMCPU_ASSERT_EMT(pVCpu);
 
@@ -10060,5 +10062,5 @@
     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
     /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
-    if (VMMR0ThreadCtxHooksAreRegistered(pVCpu))
+    if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
         return VINF_SUCCESS;
     return VINF_EM_RAW_INTERRUPT;
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 55862)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 55863)
@@ -447,104 +447,4 @@
 
 /**
- * Creates R0 thread-context hooks for the current EMT thread.
- *
- * @returns VBox status code.
- * @param   pVCpu       Pointer to the VMCPU.
- *
- * @thread  EMT(pVCpu)
- */
-VMMR0_INT_DECL(int) VMMR0ThreadCtxHooksCreate(PVMCPU pVCpu)
-{
-    VMCPU_ASSERT_EMT(pVCpu);
-    Assert(pVCpu->vmm.s.hR0ThreadCtx == NIL_RTTHREADCTX);
-#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
-    int rc = RTThreadCtxHooksCreate(&pVCpu->vmm.s.hR0ThreadCtx);
-    if (   RT_FAILURE(rc)
-        && rc != VERR_NOT_SUPPORTED)
-    {
-        Log(("RTThreadCtxHooksCreate failed! rc=%Rrc pVCpu=%p idCpu=%RU32\n", rc, pVCpu, pVCpu->idCpu));
-        return rc;
-    }
-#endif
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Releases the object reference for the thread-context hook.
- *
- * @param   pVCpu       Pointer to the VMCPU.
- * @remarks Can be called from any thread.
- */
-VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksRelease(PVMCPU pVCpu)
-{
-    RTThreadCtxHooksRelease(pVCpu->vmm.s.hR0ThreadCtx);
-}
-
-
-/**
- * Registers the thread-context hook for this VCPU.
- *
- * @returns VBox status code.
- * @param   pVCpu           Pointer to the VMCPU.
- * @param   pfnThreadHook   Pointer to the thread-context callback.
- *
- * @thread  EMT(pVCpu)
- */
-VMMR0_INT_DECL(int) VMMR0ThreadCtxHooksRegister(PVMCPU pVCpu, PFNRTTHREADCTXHOOK pfnThreadHook)
-{
-    VMCPU_ASSERT_EMT(pVCpu);
-    return RTThreadCtxHooksRegister(pVCpu->vmm.s.hR0ThreadCtx, pfnThreadHook, pVCpu);
-}
-
-
-/**
- * Deregisters the thread-context hook for this VCPU.
- *
- * @param   pVCpu       Pointer to the VMCPU.
- *
- * @thread  EMT(pVCpu)
- */
-VMMR0_INT_DECL(void) VMMR0ThreadCtxHooksDeregister(PVMCPU pVCpu)
-{
-    /* Clear the VCPU <-> host CPU mapping as we've left HM context. See @bugref{7726} comment #19. */
-    ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
-
-    if (pVCpu->vmm.s.hR0ThreadCtx != NIL_RTTHREADCTX)
-    {
-        Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-        int rc = RTThreadCtxHooksDeregister(pVCpu->vmm.s.hR0ThreadCtx);
-        AssertRC(rc);
-    }
-}
-
-
-/**
- * Whether thread-context hooks are created (implying they're supported) on this
- * platform.
- *
- * @returns true if the hooks are created, false otherwise.
- * @param   pVCpu       Pointer to the VMCPU.
- */
-VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreCreated(PVMCPU pVCpu)
-{
-    return pVCpu->vmm.s.hR0ThreadCtx != NIL_RTTHREADCTX;
-}
-
-
-/**
- * Whether thread-context hooks are registered for this VCPU.
- *
- * @returns true if registered, false otherwise.
- * @param   pVCpu       Pointer to the VMCPU.
- */
-VMMR0_INT_DECL(bool) VMMR0ThreadCtxHooksAreRegistered(PVMCPU pVCpu)
-{
-    return RTThreadCtxHooksAreRegistered(pVCpu->vmm.s.hR0ThreadCtx);
-}
-
-
-/**
  * VMM ring-0 thread-context callback.
  *
@@ -563,5 +463,5 @@
     switch (enmEvent)
     {
-        case RTTHREADCTXEVENT_RESUMED:
+        case RTTHREADCTXEVENT_IN:
         {
             /*
@@ -571,5 +471,9 @@
              * ad infinitum). Let's just disable preemption for now...
              */
-            HM_DISABLE_PREEMPT();
+            /** @todo r=bird: I don't believe the above. The linux code is clearly enabling
+             *        preemption after doing the callout (one or two functions up the
+             *        call chain). */
+            RTTHREADPREEMPTSTATE ParanoidPreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+            RTThreadPreemptDisable(&ParanoidPreemptState);
 
             /* We need to update the VCPU <-> host CPU mapping. */
@@ -589,9 +493,9 @@
 
             /* Restore preemption. */
-            HM_RESTORE_PREEMPT();
+            RTThreadPreemptRestore(&ParanoidPreemptState);
             break;
         }
 
-        case RTTHREADCTXEVENT_PREEMPTING:
+        case RTTHREADCTXEVENT_OUT:
         {
             /* Invoke the HM-specific thread-context callback. */
@@ -612,4 +516,110 @@
             break;
     }
+}
+
+
+/**
+ * Creates thread switching hook for the current EMT thread.
+ *
+ * This is called by GVMMR0CreateVM and GVMMR0RegisterVCpu.  If the host
+ * platform does not implement switcher hooks, no hooks will be create and the
+ * member set to NIL_RTTHREADCTXHOOK.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       Pointer to the cross context CPU structure.
+ * @thread  EMT(pVCpu)
+ */
+VMMR0_INT_DECL(int) VMMR0ThreadCtxHookCreateForEmt(PVMCPU pVCpu)
+{
+    VMCPU_ASSERT_EMT(pVCpu);
+    Assert(pVCpu->vmm.s.hCtxHook == NIL_RTTHREADCTXHOOK);
+
+    int rc = RTThreadCtxHookCreate(&pVCpu->vmm.s.hCtxHook, 0, vmmR0ThreadCtxCallback, pVCpu);
+    if (RT_SUCCESS(rc))
+        return rc;
+
+    pVCpu->vmm.s.hCtxHook = NIL_RTTHREADCTXHOOK;
+    if (rc == VERR_NOT_SUPPORTED)
+        return VINF_SUCCESS;
+
+    LogRelMax(32, ("RTThreadCtxHookCreate failed! rc=%Rrc pVCpu=%p idCpu=%RU32\n", rc, pVCpu, pVCpu->idCpu));
+    return VINF_SUCCESS; /* Just ignore it, we can live without context hooks. */
+}
+
+
+/**
+ * Destroys the thread switching hook for the specified VCPU.
+ *
+ * @param   pVCpu       Pointer to the cross context CPU structure.
+ * @remarks Can be called from any thread.
+ */
+VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDestroyForEmt(PVMCPU pVCpu)
+{
+    int rc = RTThreadCtxHookDestroy(pVCpu->vmm.s.hCtxHook);
+    AssertRC(rc);
+}
+
+
+/**
+ * Disables the thread switching hook for this VCPU (if we got one).
+ *
+ * @param   pVCpu       Pointer to the cross context CPU structure.
+ * @thread  EMT(pVCpu)
+ *
+ * @remarks This also clears VMCPU::idHostCpu, so the mapping is invalid after
+ *          this call.  This means you have to be careful with what you do!
+ */
+VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDisable(PVMCPU pVCpu)
+{
+    /*
+     * Clear the VCPU <-> host CPU mapping as we've left HM context.
+     * @bugref{7726} comment #19 explains the need for this trick:
+     *
+     *      hmR0VmxCallRing3Callback/hmR0SvmCallRing3Callback &
+     *      hmR0VmxLeaveSession/hmR0SvmLeaveSession disables context hooks during
+     *      longjmp & normal return to ring-3, which opens a window where we may be
+     *      rescheduled without changing VMCPUID::idHostCpu and cause confusion if
+     *      the CPU starts executing a different EMT.  Both functions first disables
+     *      preemption and then calls HMR0LeaveCpu which invalids idHostCpu, leaving
+     *      an opening for getting preempted.
+     */
+    /** @todo Make HM not need this API!  Then we could leave the hooks enabled
+     *        all the time. */
+    /** @todo move this into the context hook disabling if(). */
+    ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
+
+    /*
+     * Disable the context hook, if we got one.
+     */
+    if (pVCpu->vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK)
+    {
+        Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+        int rc = RTThreadCtxHookDisable(pVCpu->vmm.s.hCtxHook);
+        AssertRC(rc);
+    }
+}
+
+
+/**
+ * Internal version of VMMR0ThreadCtxHooksAreRegistered.
+ *
+ * @returns true if registered, false otherwise.
+ * @param   pVCpu       Pointer to the VMCPU.
+ */
+DECLINLINE(bool) vmmR0ThreadCtxHookIsEnabled(PVMCPU pVCpu)
+{
+    return RTThreadCtxHookIsEnabled(pVCpu->vmm.s.hCtxHook);
+}
+
+
+/**
+ * Whether thread-context hooks are registered for this VCPU.
+ *
+ * @returns true if registered, false otherwise.
+ * @param   pVCpu       Pointer to the VMCPU.
+ */
+VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPU pVCpu)
+{
+    return vmmR0ThreadCtxHookIsEnabled(pVCpu);
 }
 
@@ -993,5 +1003,5 @@
              * Disable preemption.
              */
-            Assert(!VMMR0ThreadCtxHooksAreRegistered(pVCpu));
+            Assert(!vmmR0ThreadCtxHookIsEnabled(pVCpu));
             RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
             RTThreadPreemptDisable(&PreemptState);
@@ -1038,8 +1048,8 @@
                      * Register thread-context hooks if required.
                      */
-                    if (    VMMR0ThreadCtxHooksAreCreated(pVCpu)
-                        && !VMMR0ThreadCtxHooksAreRegistered(pVCpu))
+                    if (    pVCpu->vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK
+                        && !RTThreadCtxHookIsEnabled(pVCpu->vmm.s.hCtxHook))
                     {
-                        rc = VMMR0ThreadCtxHooksRegister(pVCpu, vmmR0ThreadCtxCallback);
+                        rc = RTThreadCtxHookEnable(pVCpu->vmm.s.hCtxHook);
                         AssertRC(rc);
                     }
@@ -1057,5 +1067,5 @@
                          * we're in HM context.
                          */
-                        if (VMMR0ThreadCtxHooksAreRegistered(pVCpu))
+                        if (vmmR0ThreadCtxHookIsEnabled(pVCpu))
                         {
                             fPreemptRestored = true;
@@ -1080,5 +1090,5 @@
                             rc = VERR_VMM_WRONG_HM_VMCPU_STATE;
                         }
-                        else if (RT_UNLIKELY(VMMR0ThreadCtxHooksAreRegistered(pVCpu)))
+                        else if (RT_UNLIKELY(vmmR0ThreadCtxHookIsEnabled(pVCpu)))
                         {
                             pVM->vmm.s.szRing0AssertMsg1[0] = '\0';
@@ -1091,4 +1101,6 @@
                     }
                     STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
+
+                    /** @todo shouldn't we disable the ctx hook here??? */
                 }
                 /*
Index: /trunk/src/VBox/VMM/VMMR3/VMM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 55862)
+++ /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 55863)
@@ -541,5 +541,5 @@
 
     /* Log whether thread-context hooks are used (on Linux this can depend on how the kernel is configured). */
-    if (pVM->aCpus[0].vmm.s.hR0ThreadCtx != NIL_RTTHREADCTX)
+    if (pVM->aCpus[0].vmm.s.hCtxHook != NIL_RTTHREADCTXHOOK)
         LogRel(("VMM: Thread-context hooks enabled!\n"));
     else
Index: /trunk/src/VBox/VMM/include/HMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/HMInternal.h	(revision 55862)
+++ /trunk/src/VBox/VMM/include/HMInternal.h	(revision 55863)
@@ -221,8 +221,28 @@
 #define HM_VTX_TOTAL_DEVHEAP_MEM        (HM_EPT_IDENTITY_PG_TABLE_SIZE + HM_VTX_TSS_SIZE)
 
+
+/** @name Macros for enabling and disabling preemption.
+ * These are really just for hiding the RTTHREADPREEMPTSTATE and asserting that
+ * preemption has already been disabled when there is no context hook.
+ * @{ */
+#ifdef VBOX_STRICT
+# define HM_DISABLE_PREEMPT() \
+    RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \
+    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD) || VMMR0ThreadCtxHookIsEnabled(pVCpu)); \
+    RTThreadPreemptDisable(&PreemptStateInternal)
+#else
+# define HM_DISABLE_PREEMPT() \
+    RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \
+    RTThreadPreemptDisable(&PreemptStateInternal)
+#endif /* VBOX_STRICT */
+#define HM_RESTORE_PREEMPT()    do { RTThreadPreemptRestore(&PreemptStateInternal); } while(0)
+/** @} */
+
+
 /** Enable for TPR guest patching. */
 #define VBOX_HM_WITH_GUEST_PATCHING
 
-/** HM SSM version
+/** @name HM saved state versions
+ * @{
  */
 #ifdef VBOX_HM_WITH_GUEST_PATCHING
@@ -234,4 +254,5 @@
 #endif
 #define HM_SAVED_STATE_VERSION_2_0_X            3
+/** @} */
 
 /**
Index: /trunk/src/VBox/VMM/include/VMMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/VMMInternal.h	(revision 55862)
+++ /trunk/src/VBox/VMM/include/VMMInternal.h	(revision 55863)
@@ -420,13 +420,6 @@
     R0PTRTYPE(PVMMR0LOGGER)     pR0LoggerR0;
 
-    /** @name Thread-context hooks.
-     *  @{*/
-    R0PTRTYPE(RTTHREADCTX)      hR0ThreadCtx;
-#if HC_ARCH_BITS == 32
-    uint32_t                    u32Padding;
-#else
-    uint64_t                    u64Padding;
-#endif
-    /** @} */
+    /** Thread context switching hook (ring-0). */
+    RTTHREADCTXHOOK             hCtxHook;
 
     /** @name Rendezvous
@@ -435,8 +428,8 @@
      *  attempts at recursive rendezvous. */
     bool volatile               fInRendezvous;
-    bool                        afPadding[HC_ARCH_BITS == 32 ? 3 : 7];
+    bool                        afPadding[HC_ARCH_BITS == 32 ? 3+4 : 7+8];
     /** @} */
 
-    /** @name Raw-mode context tracting data.
+    /** @name Raw-mode context tracing data.
      * @{ */
     SUPDRVTRACERUSRCTX          TracerCtx;
Index: /trunk/src/VBox/VMM/include/VMMInternal.mac
===================================================================
--- /trunk/src/VBox/VMM/include/VMMInternal.mac	(revision 55862)
+++ /trunk/src/VBox/VMM/include/VMMInternal.mac	(revision 55863)
@@ -108,16 +108,11 @@
         .pR0LoggerR0            RTR0PTR_RES 1
 
-        .hR0ThreadCtx           RTR0PTR_RES 1
-%if HC_ARCH_BITS == 32
-        .u32Padding             resd 1
-%else
-        .u64Padding             resq 1
-%endif
+        .hCtxHook               RTR0PTR_RES 1
 
         .fInRendezvous          resb 1
 %if HC_ARCH_BITS == 32
-        .afPadding              resb 3
+        .afPadding              resb 3+4
 %else
-        .afPadding              resb 7
+        .afPadding              resb 7+8
 %endif
 
