Index: /trunk/include/iprt/thread.h
===================================================================
--- /trunk/include/iprt/thread.h	(revision 47205)
+++ /trunk/include/iprt/thread.h	(revision 47206)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -616,4 +616,6 @@
  * @returns IPRT status code.
  * @param   phThreadCtx         Where to store the thread-context handle.
+ *
+ * @remarks Must be called with preemption enabled!
  */
 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx);
@@ -626,4 +628,6 @@
  *
  * @param   phThreadCtx         Pointer to the thread-context handle.
+ *
+ * @remarks Must be called with preemption enabled!
  */
 RTDECL(void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx);
@@ -638,4 +642,6 @@
  *                              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);
@@ -646,4 +652,6 @@
  * @returns IPRT status code.
  * @param   phThreadCtx         Pointer to the thread-context handle.
+ *
+ * @remarks Can be called with preemption disabled.
  */
 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx);
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 47205)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 47206)
@@ -1929,5 +1929,4 @@
 	r0drv/mpnotification-r0drv.c \
 	r0drv/powernotification-r0drv.c \
-	r0drv/generic/threadctxhooks-r0drv-generic.cpp \
 	r0drv/solaris/RTLogWriteDebugger-r0drv-solaris.c \
 	r0drv/solaris/RTMpPokeCpu-r0drv-solaris.c \
@@ -1948,4 +1947,5 @@
 	r0drv/solaris/thread-r0drv-solaris.c \
 	r0drv/solaris/thread2-r0drv-solaris.c \
+	r0drv/solaris/threadctxhooks-r0drv-solaris.c \
 	r0drv/solaris/time-r0drv-solaris.c \
 	r0drv/solaris/timer-r0drv-solaris.c
Index: /trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c	(revision 47205)
+++ /trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c	(revision 47206)
@@ -45,5 +45,5 @@
 *******************************************************************************/
 /**
- * The internal thread-context event.
+ * The internal thread-context object.
  */
 typedef struct RTTHREADCTXINT
@@ -109,5 +109,5 @@
  * Worker function for RTThreadCtxHooks(Deregister|Destroy)().
  *
- * @param   pThis   Pointer to the internal thread-context struct.
+ * @param   pThis   Pointer to the internal thread-context object.
  */
 DECLINLINE(void) rtThreadCtxHooksDeregister(PRTTHREADCTXINT pThis)
@@ -150,4 +150,5 @@
     AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
     Assert(pThis->hOwner == RTThreadSelf());
+    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
 
     /*
Index: /trunk/src/VBox/Runtime/r0drv/solaris/the-solaris-kernel.h
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/the-solaris-kernel.h	(revision 47205)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/the-solaris-kernel.h	(revision 47206)
@@ -58,4 +58,5 @@
 #include <sys/ctf_api.h>
 #include <sys/modctl.h>
+#include <sys/proc.h>
 
 #undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */
Index: /trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c	(revision 47206)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c	(revision 47206)
@@ -0,0 +1,217 @@
+/* $Id$ */
+/** @file
+ * IPRT - Thread-Context Hook, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/mem.h>
+#include <iprt/assert.h>
+#include <iprt/thread.h>
+#include <iprt/err.h>
+#include <iprt/asm.h>
+#include "internal/thread.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * The internal thread-context object.
+ */
+typedef struct RTTHREADCTXINT
+{
+    /** Magic value (RTTHREADCTXINT_MAGIC). */
+    uint32_t volatile           u32Magic;
+    /** The thread handle (owner) for which the context-hooks are registered. */
+    RTTHREAD                    hOwner;
+    /** Pointer to the registered thread-context hook. */
+    PFNRTTHREADCTXHOOK          pfnThreadCtxHook;
+    /** User argument passed to the thread-context hook. */
+    void                       *pvUser;
+    /** Whether this handle has any hooks registered or not. */
+    bool                        fRegistered;
+} RTTHREADCTXINT, *PRTTHREADCTXINT;
+
+
+
+/**
+ * Hook function for the thread-preempting event.
+ *
+ * @param   pvThreadCtxInt  Opaque pointer to the internal thread-context
+ *                          object.
+ *
+ * @remarks Called with the with preemption disabled!
+ */
+static void rtThreadCtxHooksSolPreempting(void *pvThreadCtxInt)
+{
+    PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
+    AssertPtr(pThis);
+    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+
+    if (pThis->fRegistered)
+    {
+        Assert(pThis->pfnThreadCtxHook);
+        pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
+    }
+}
+
+
+/**
+ * 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;
+    AssertPtr(pThis);
+    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+
+    if (pThis->fRegistered)
+    {
+        Assert(pThis->pfnThreadCtxHook);
+        pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
+    }
+}
+
+
+RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
+{
+    PRTTHREADCTXINT pThis;
+    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+
+    pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis));
+    if (RT_UNLIKELY(!pThis))
+        return VERR_NO_MEMORY;
+    pThis->u32Magic    = RTTHREADCTXINT_MAGIC;
+    pThis->hOwner      = RTThreadSelf();
+    pThis->fRegistered = false;
+
+    /*
+     * 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
+     * invoke the consumer's hook or not.
+     */
+    installctx(curthread,
+               pThis,
+               rtThreadCtxHooksSolPreempting,
+               rtThreadCtxHooksSolResumed,
+               NULL,                            /* fork */
+               NULL,                            /* lwp_create */
+               NULL,                            /* exit */
+               NULL);                           /* free */
+
+    *phThreadCtx = pThis;
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXINT pThis = hThreadCtx;
+    if (pThis == NIL_RTTHREADCTX)
+        return;
+    AssertPtr(pThis);
+    AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
+    Assert(pThis->hOwner == RTThreadSelf());
+    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+
+    /*
+     * Deregister the hook.
+     */
+    int rc = removectx(curthread,
+                       pThis,
+                       rtThreadCtxHooksSolPreempting,
+                       rtThreadCtxHooksSolResumed,
+                       NULL,                            /* fork */
+                       NULL,                            /* lwp_create */
+                       NULL,                            /* exit */
+                       NULL);                           /* free */
+    AssertMsg(rc, ("removectx failed. rc=%d\n", rc));
+    NOREF(rc);
+
+    /*
+     * Destroy the object.
+     */
+    ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
+    RTMemFree(pThis);
+}
+
+
+RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXINT pThis = hThreadCtx;
+    if (pThis == NIL_RTTHREADCTX)
+        return VINF_SUCCESS;
+    AssertPtr(pThis);
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                    VERR_INVALID_HANDLE);
+    Assert(pThis->hOwner == RTThreadSelf());
+
+    /*
+     * Register the callback.
+     */
+    pThis->pvUser           = pvUser;
+    pThis->pfnThreadCtxHook = pfnThreadCtxHook;
+    pThis->fRegistered      = true;
+
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
+{
+    /*
+     * Validate input.
+     */
+    PRTTHREADCTXINT pThis = hThreadCtx;
+    if (pThis == NIL_RTTHREADCTX)
+        return VINF_SUCCESS;
+    AssertPtr(pThis);
+    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
+                    VERR_INVALID_HANDLE);
+    Assert(pThis->hOwner == RTThreadSelf());
+    Assert(pThis->fRegistered);
+
+    /*
+     * Deregister the callback.
+     */
+    pThis->fRegistered = false;
+
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.cpp	(revision 47205)
+++ /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.cpp	(revision 47206)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2009-2011 Oracle Corporation
+ * Copyright (C) 2009-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -372,5 +372,8 @@
 
             RTThreadCtxHooksDeregister(hThreadCtx);
+
+            Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
             RTThreadCtxHooksDestroy(hThreadCtx);
+
             RTMemFree(pCtxData);
             break;
Index: /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.h
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.h	(revision 47205)
+++ /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.h	(revision 47206)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2009-2010 Oracle Corporation
+ * Copyright (C) 2009-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
Index: /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemptionDriver.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemptionDriver.cpp	(revision 47205)
+++ /trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemptionDriver.cpp	(revision 47206)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2009-2010 Oracle Corporation
+ * Copyright (C) 2009-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
