VirtualBox

Changeset 55863 in vbox for trunk/src/VBox/Runtime


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

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

Location:
trunk/src/VBox/Runtime
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/include/internal/magics.h

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

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

    r54872 r55863  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Thread-Context Hook, Ring-0 Driver, Linux.
     3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Linux.
    44 */
    55
     
    4242#include "internal/thread.h"
    4343
     44
    4445/*
    45  * Linux kernel 2.6.23 introduced thread-context hooks but RedHat 2.6.18 kernels
     46 * Linux kernel 2.6.23 introduced preemption notifiers but RedHat 2.6.18 kernels
    4647 * got it backported.
    4748 */
     
    5253*******************************************************************************/
    5354/**
    54  * The internal thread-context object.
    55  */
    56 typedef struct RTTHREADCTXINT
    57 {
    58     /** Magic value (RTTHREADCTXINT_MAGIC). */
     55 * The internal hook object for linux.
     56 */
     57typedef struct RTTHREADCTXHOOKINT
     58{
     59    /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */
    5960    uint32_t volatile           u32Magic;
    60     /** The thread handle (owner) for which the context-hooks are registered. */
     61    /** The thread handle (owner) for which the hook is registered. */
    6162    RTNATIVETHREAD              hOwner;
    6263    /** The preemption notifier object. */
    63     struct preempt_notifier     hPreemptNotifier;
    64     /** Whether this handle has any hooks registered or not. */
    65     bool                        fRegistered;
    66     /** Pointer to the registered thread-context hook. */
    67     PFNRTTHREADCTXHOOK          pfnThreadCtxHook;
    68     /** User argument passed to the thread-context hook. */
     64    struct preempt_notifier     LnxPreemptNotifier;
     65    /** Whether the hook is enabled or not.  If enabled, the LnxPreemptNotifier
     66     * is linked into the owning thread's list of preemption callouts. */
     67    bool                        fEnabled;
     68    /** Pointer to the user callback. */
     69    PFNRTTHREADCTXHOOK          pfnCallback;
     70    /** User argument passed to the callback. */
    6971    void                       *pvUser;
    70     /** The thread-context operations. */
    71     struct preempt_ops          hPreemptOps;
    72     /** The reference count for this object. */
    73     uint32_t volatile           cRefs;
     72    /** The linux callbacks. */
     73    struct preempt_ops          PreemptOps;
    7474#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 19) && defined(RT_ARCH_AMD64)
    7575    /** Starting with 3.1.19, the linux kernel doesn't restore kernel RFLAGS during
     
    7777    RTCCUINTREG                 fSavedRFlags;
    7878#endif
    79 } RTTHREADCTXINT, *PRTTHREADCTXINT;
     79} RTTHREADCTXHOOKINT;
     80typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT;
    8081
    8182
    8283/**
    83  * Hook function for the thread-preempting event.
     84 * Hook function for the thread schedule out event.
    8485 *
    8586 * @param   pPreemptNotifier    Pointer to the preempt_notifier struct.
    86  * @param   pNext               Pointer to the task that is preempting the
    87  *                              current thread.
     87 * @param   pNext               Pointer to the task that is being scheduled
     88 *                              instead of the current thread.
    8889 *
    8990 * @remarks Called with the rq (runqueue) lock held and with preemption and
     
    9293static void rtThreadCtxHooksLnxSchedOut(struct preempt_notifier *pPreemptNotifier, struct task_struct *pNext)
    9394{
    94     PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
     95    PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier);
    9596#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    9697    RTCCUINTREG fSavedEFlags = ASMGetFlags();
     
    99100
    100101    AssertPtr(pThis);
    101     AssertPtr(pThis->pfnThreadCtxHook);
    102     Assert(pThis->fRegistered);
     102    AssertPtr(pThis->pfnCallback);
     103    Assert(pThis->fEnabled);
    103104    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    104105
    105     pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
     106    pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser);
    106107
    107108#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     
    115116
    116117/**
    117  * Hook function for the thread-resumed event.
     118 * Hook function for the thread schedule in event.
    118119 *
    119120 * @param   pPreemptNotifier    Pointer to the preempt_notifier struct.
    120  * @param   iCpu                The CPU this thread is scheduled on.
     121 * @param   iCpu                The CPU this thread is being scheduled on.
    121122 *
    122123 * @remarks Called without holding the rq (runqueue) lock and with preemption
    123124 *          enabled!
     125 * @todo    r=bird: Preemption is of course disabled when it is called.
    124126 */
    125127static void rtThreadCtxHooksLnxSchedIn(struct preempt_notifier *pPreemptNotifier, int iCpu)
    126128{
    127     PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
     129    PRTTHREADCTXHOOKINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXHOOKINT, LnxPreemptNotifier);
    128130#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    129131    RTCCUINTREG fSavedEFlags = ASMGetFlags();
     
    132134
    133135    AssertPtr(pThis);
    134     AssertPtr(pThis->pfnThreadCtxHook);
    135     Assert(pThis->fRegistered);
    136 
    137     pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
     136    AssertPtr(pThis->pfnCallback);
     137    Assert(pThis->fEnabled);
     138
     139    pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser);
    138140
    139141#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     
    152154 * @param   pThis   Pointer to the internal thread-context object.
    153155 */
    154 DECLINLINE(void) rtThreadCtxHooksDeregister(PRTTHREADCTXINT pThis)
    155 {
    156     preempt_notifier_unregister(&pThis->hPreemptNotifier);
    157     pThis->hPreemptOps.sched_out = NULL;
    158     pThis->hPreemptOps.sched_in  = NULL;
    159     pThis->fRegistered           = false;
    160 }
    161 
    162 
    163 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
    164 {
    165     PRTTHREADCTXINT pThis;
     156DECLINLINE(void) rtThreadCtxHookDisable(PRTTHREADCTXHOOKINT pThis)
     157{
     158    Assert(pThis->PreemptOps.sched_out == rtThreadCtxHooksLnxSchedOut);
     159    Assert(pThis->PreemptOps.sched_in  == rtThreadCtxHooksLnxSchedIn);
     160    preempt_disable();
     161    preempt_notifier_unregister(&pThis->LnxPreemptNotifier);
     162    pThis->fEnabled = false;
     163    preempt_enable();
     164}
     165
     166
     167RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
     168{
     169    /*
     170     * Validate input.
     171     */
     172    PRTTHREADCTXHOOKINT pThis;
    166173    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    167 
    168     pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis));
     174    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
     175    AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
     176
     177    /*
     178     * Allocate and initialize a new hook.  We don't register it yet, just
     179     * create it.
     180     */
     181    pThis = (PRTTHREADCTXHOOKINT)RTMemAllocZ(sizeof(*pThis));
    169182    if (RT_UNLIKELY(!pThis))
    170183        return VERR_NO_MEMORY;
    171     pThis->u32Magic    = RTTHREADCTXINT_MAGIC;
    172     pThis->hOwner      = RTThreadNativeSelf();
    173     pThis->fRegistered = false;
    174     preempt_notifier_init(&pThis->hPreemptNotifier, &pThis->hPreemptOps);
    175     pThis->cRefs       = 1;
    176 
    177     *phThreadCtx = pThis;
     184    pThis->u32Magic     = RTTHREADCTXHOOKINT_MAGIC;
     185    pThis->hOwner       = RTThreadNativeSelf();
     186    pThis->fEnabled     = false;
     187    pThis->pfnCallback  = pfnCallback;
     188    pThis->pvUser       = pvUser;
     189    preempt_notifier_init(&pThis->LnxPreemptNotifier, &pThis->PreemptOps);
     190    pThis->PreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut;
     191    pThis->PreemptOps.sched_in  = rtThreadCtxHooksLnxSchedIn;
     192
     193    *phCtxHook = pThis;
    178194    return VINF_SUCCESS;
    179195}
    180 RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
    181 
    182 
    183 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
    184 {
    185     /*
    186      * Validate input.
    187      */
    188     uint32_t        cRefs;
    189     PRTTHREADCTXINT pThis = hThreadCtx;
    190     AssertPtr(pThis);
    191     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
    192                     UINT32_MAX);
    193 
    194     cRefs = ASMAtomicIncU32(&pThis->cRefs);
    195     Assert(cRefs < UINT32_MAX / 2);
    196     return cRefs;
    197 }
    198 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain);
    199 
    200 
    201 
    202 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
    203 {
    204     /*
    205      * Validate input.
    206      */
    207     uint32_t        cRefs;
    208     PRTTHREADCTXINT pThis = hThreadCtx;
    209     if (pThis == NIL_RTTHREADCTX)
    210         return 0;
    211 
    212     AssertPtr(pThis);
    213     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
    214                     UINT32_MAX);
     196RT_EXPORT_SYMBOL(RTThreadCtxHookCreate);
     197
     198
     199RTDECL(int ) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook)
     200{
     201    /*
     202     * Validate input.
     203     */
     204    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     205    if (pThis == NIL_RTTHREADCTXHOOK)
     206        return VINF_SUCCESS;
     207    AssertPtr(pThis);
     208    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     209                    VERR_INVALID_HANDLE);
    215210    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    216 
    217     cRefs = ASMAtomicDecU32(&pThis->cRefs);
    218     if (!cRefs)
     211    Assert(pThis->fEnabled || pThis->hOwner == RTThreadNativeSelf());
     212
     213    /*
     214     * If there's still a registered thread-context hook, deregister it now before destroying the object.
     215     */
     216    if (pThis->fEnabled)
    219217    {
    220         /*
    221          * If there's still a registered thread-context hook, deregister it now before destroying the object.
    222          */
    223         if (pThis->fRegistered)
    224             rtThreadCtxHooksDeregister(pThis);
    225 
    226         /*
    227          * Paranoia... but since these are ring-0 threads we can't be too careful.
    228          */
    229         Assert(!pThis->fRegistered);
    230         Assert(!pThis->hPreemptOps.sched_out);
    231         Assert(!pThis->hPreemptOps.sched_in);
    232 
    233         ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
    234         RTMemFree(pThis);
     218        Assert(pThis->hOwner == RTThreadNativeSelf());
     219        rtThreadCtxHookDisable(pThis);
     220        Assert(!pThis->fEnabled); /* paranoia */
    235221    }
    236     else
    237         Assert(cRefs < UINT32_MAX / 2);
    238 
    239     return cRefs;
    240 }
    241 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease);
    242 
    243 
    244 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
    245 {
    246     /*
    247      * Validate input.
    248      */
    249     PRTTHREADCTXINT pThis = hThreadCtx;
    250     if (pThis == NIL_RTTHREADCTX)
    251         return VERR_INVALID_HANDLE;
    252     AssertPtr(pThis);
    253     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     222
     223    ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
     224    RTMemFree(pThis);
     225
     226    return VINF_SUCCESS;
     227}
     228RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy);
     229
     230
     231RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
     232{
     233    /*
     234     * Validate input.
     235     */
     236    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     237    AssertPtr(pThis);
     238    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
    254239                    VERR_INVALID_HANDLE);
    255240    Assert(pThis->hOwner == RTThreadNativeSelf());
    256     Assert(!pThis->hPreemptOps.sched_out);
    257     Assert(!pThis->hPreemptOps.sched_in);
    258 
    259     /*
    260      * Register the callback.
    261      */
    262     pThis->hPreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut;
    263     pThis->hPreemptOps.sched_in  = rtThreadCtxHooksLnxSchedIn;
    264     pThis->pvUser                = pvUser;
    265     pThis->pfnThreadCtxHook      = pfnThreadCtxHook;
    266     pThis->fRegistered           = true;
    267     preempt_notifier_register(&pThis->hPreemptNotifier);
     241    Assert(!pThis->fEnabled);
     242    if (!pThis->fEnabled)
     243    {
     244        Assert(pThis->PreemptOps.sched_out == rtThreadCtxHooksLnxSchedOut);
     245        Assert(pThis->PreemptOps.sched_in == rtThreadCtxHooksLnxSchedIn);
     246
     247        /*
     248         * Register the callback.
     249         */
     250        preempt_disable();
     251        pThis->fEnabled = true;
     252        preempt_notifier_register(&pThis->LnxPreemptNotifier);
     253        preempt_enable();
     254    }
    268255
    269256    return VINF_SUCCESS;
    270257}
    271 RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
    272 
    273 
    274 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
    275 {
    276     /*
    277      * Validate input.
    278      */
    279     PRTTHREADCTXINT pThis = hThreadCtx;
    280     if (pThis == NIL_RTTHREADCTX)
    281         return VERR_INVALID_HANDLE;
    282     AssertPtr(pThis);
    283     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
    284                     VERR_INVALID_HANDLE);
    285     Assert(pThis->hOwner == RTThreadNativeSelf());
    286     Assert(pThis->fRegistered);
    287 
    288     /*
    289      * Deregister the callback.
    290      */
    291     rtThreadCtxHooksDeregister(pThis);
     258RT_EXPORT_SYMBOL(RTThreadCtxHookEnable);
     259
     260
     261RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
     262{
     263    /*
     264     * Validate input.
     265     */
     266    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     267    if (pThis != NIL_RTTHREADCTXHOOK)
     268    {
     269        AssertPtr(pThis);
     270        AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     271                        VERR_INVALID_HANDLE);
     272        Assert(pThis->hOwner == RTThreadNativeSelf());
     273
     274        /*
     275         * Deregister the callback.
     276         */
     277        if (pThis->fEnabled)
     278            rtThreadCtxHookDisable(pThis);
     279    }
    292280    return VINF_SUCCESS;
    293281}
    294 RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
    295 
    296 
    297 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
    298 {
    299     /*
    300      * Validate input.
    301      */
    302     PRTTHREADCTXINT pThis = hThreadCtx;
    303     if (pThis == NIL_RTTHREADCTX)
     282RT_EXPORT_SYMBOL(RTThreadCtxHookDisable);
     283
     284
     285RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
     286{
     287    /*
     288     * Validate input.
     289     */
     290    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     291    if (pThis == NIL_RTTHREADCTXHOOK)
    304292        return false;
    305293    AssertPtr(pThis);
    306     AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
    307 
    308     return pThis->fRegistered;
     294    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     295                    false);
     296
     297    return pThis->fEnabled;
    309298}
    310299
    311300#else    /* Not supported / Not needed */
    312 
    313 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
    314 {
    315     NOREF(phThreadCtx);
    316     return VERR_NOT_SUPPORTED;
    317 }
    318 RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
    319 
    320 
    321 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
    322 {
    323     NOREF(hThreadCtx);
    324     return UINT32_MAX;
    325 }
    326 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain);
    327 
    328 
    329 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
    330 {
    331     NOREF(hThreadCtx);
    332     return UINT32_MAX;
    333 }
    334 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease);
    335 
    336 
    337 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
    338 {
    339     NOREF(hThreadCtx);
    340     NOREF(pfnThreadCtxHook);
    341     NOREF(pvUser);
    342     return VERR_NOT_SUPPORTED;
    343 }
    344 RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
    345 
    346 
    347 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
    348 {
    349     NOREF(hThreadCtx);
    350     return VERR_NOT_SUPPORTED;
    351 }
    352 RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
    353 
    354 
    355 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
    356 {
    357     NOREF(hThreadCtx);
    358     return false;
    359 }
    360 RT_EXPORT_SYMBOL(RTThreadCtxHooksAreRegistered);
    361 
     301# include "../generic/threadctxhooks-r0drv-generic.cpp"
    362302#endif   /* Not supported / Not needed */
    363303
  • trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c

    r55860 r55863  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Thread-Context Hook, Ring-0 Driver, Solaris.
     3 * IPRT - Thread Context Switching Hook, Ring-0 Driver, Solaris.
    44 */
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4545*******************************************************************************/
    4646/**
    47  * The internal thread-context object.
    48  */
    49 typedef struct RTTHREADCTXINT
    50 {
    51     /** Magic value (RTTHREADCTXINT_MAGIC). */
     47 * The internal hook object for solaris.
     48 */
     49typedef struct RTTHREADCTXHOOKINT
     50{
     51    /** Magic value (RTTHREADCTXHOOKINT_MAGIC). */
    5252    uint32_t volatile           u32Magic;
    5353    /** The thread handle (owner) for which the context-hooks are registered. */
    5454    RTNATIVETHREAD              hOwner;
    55     /** Pointer to the registered thread-context hook. */
    56     PFNRTTHREADCTXHOOK          pfnThreadCtxHook;
    57     /** User argument passed to the thread-context hook. */
     55    /** Pointer to the registered callback function. */
     56    PFNRTTHREADCTXHOOK          pfnCallback;
     57    /** User argument passed to the callback function. */
    5858    void                       *pvUser;
    59     /** Whether this handle has any hooks registered or not. */
    60     bool volatile               fRegistered;
     59    /** Whether the hook is enabled or not. */
     60    bool volatile               fEnabled;
    6161    /** Number of references to this object. */
    6262    uint32_t volatile           cRefs;
    63 } RTTHREADCTXINT, *PRTTHREADCTXINT;
     63} RTTHREADCTXHOOKINT;
     64typedef RTTHREADCTXHOOKINT *PRTTHREADCTXHOOKINT;
    6465
    6566
     
    6768*   Defined Constants And Macros                                               *
    6869*******************************************************************************/
    69 /** Validates a thread-context hook handle and returns rc if not valid. */
     70/** Validates a hook handle and returns rc if not valid. */
    7071#define RTTHREADCTX_VALID_RETURN_RC(pThis, rc) \
    7172    do { \
    7273        AssertPtrReturn((pThis), (rc)); \
    73         AssertReturn((pThis)->u32Magic == RTTHREADCTXINT_MAGIC, (rc)); \
     74        AssertReturn((pThis)->u32Magic == RTTHREADCTXHOOKINT_MAGIC, (rc)); \
    7475        AssertReturn((pThis)->cRefs > 0, (rc)); \
    7576    } while (0)
     
    7778
    7879/**
    79  * Hook function for the thread-preempting event.
    80  *
    81  * @param   pvThreadCtxInt  Opaque pointer to the internal thread-context
    82  *                          object.
     80 * Hook function for the thread-save event.
     81 *
     82 * @param   pvThreadCtxInt  Opaque pointer to the internal hook object.
    8383 *
    8484 * @remarks Called with the with preemption disabled!
    8585 */
    86 static void rtThreadCtxHooksSolPreempting(void *pvThreadCtxInt)
    87 {
    88     PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
     86static void rtThreadCtxHookSolOut(void *pvThreadCtxInt)
     87{
     88    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
    8989    AssertPtr(pThis);
    9090    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    91 
    92     if (pThis->fRegistered)
    93     {
    94         Assert(pThis->pfnThreadCtxHook);
    95         pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
     91    Assert(pThis->cRefs > 0);
     92
     93    if (pThis->fEnabled)
     94    {
     95        Assert(pThis->pfnCallback);
     96        pThis->pfnCallback(RTTHREADCTXEVENT_OUT, pThis->pvUser);
    9697    }
    9798}
     
    99100
    100101/**
    101  * Hook function for the thread-resumed event.
    102  *
    103  * @param   pvThreadCtxInt  Opaque pointer to the internal thread-context
    104  *                          object.
    105  */
    106 static void rtThreadCtxHooksSolResumed(void *pvThreadCtxInt)
    107 {
    108     PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
     102 * Hook function for the thread-restore event.
     103 *
     104 * @param   pvThreadCtxInt  Opaque pointer to the internal hook object.
     105 */
     106static void rtThreadCtxHookSolIn(void *pvThreadCtxInt)
     107{
     108    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
    109109    AssertPtr(pThis);
    110110    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    111 
    112     if (pThis->fRegistered)
    113     {
    114         Assert(pThis->pfnThreadCtxHook);
    115         pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
     111    Assert(pThis->cRefs > 0);
     112
     113    if (pThis->fEnabled)
     114    {
     115        Assert(pThis->pfnCallback);
     116        pThis->pfnCallback(RTTHREADCTXEVENT_IN, pThis->pvUser);
    116117    }
    117118}
     
    121122 * Hook function for the thread-free event.
    122123 *
    123  * @param   pvThreadCtxInt      Opaque pointer to the internal thread-context
    124  *                              object.
     124 * This is used for making sure the hook object is safely released - see
     125 * RTThreadCtxHookRelease for details.
     126 *
     127 * @param   pvThreadCtxInt      Opaque pointer to the internal hook object.
    125128 * @param   fIsExec             Whether this event is triggered due to exec().
    126129 */
    127 static void rtThreadCtxHooksSolFree(void *pvThreadCtxInt, int fIsExec)
    128 {
    129     PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
     130static void rtThreadCtxHookSolFree(void *pvThreadCtxInt, int fIsExec)
     131{
     132    PRTTHREADCTXHOOKINT pThis = (PRTTHREADCTXHOOKINT)pvThreadCtxInt;
    130133    AssertPtrReturnVoid(pThis);
    131     AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
     134    AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
    132135
    133136    uint32_t cRefs = ASMAtomicReadU32(&pThis->cRefs);
    134     if (RT_UNLIKELY(!cRefs))
     137    if (cRefs > 0)
     138    {
     139        cRefs = ASMAtomicDecU32(&pThis->cRefs);
     140        if (!cRefs)
     141        {
     142            Assert(!pThis->fEnabled);
     143            ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
     144            RTMemFree(pThis);
     145        }
     146    }
     147    else
    135148    {
    136149        /* Should never happen. */
    137         AssertMsgFailed(("rtThreadCtxHooksSolFree with cRefs=0 pThis=%p\n", pThis));
    138         return;
    139     }
    140 
    141     cRefs = ASMAtomicDecU32(&pThis->cRefs);
    142     if (!cRefs)
    143     {
    144         Assert(!pThis->fRegistered);
    145         ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
    146         RTMemFree(pThis);
    147     }
    148 }
    149 
    150 
    151 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
    152 {
    153     PRTTHREADCTXINT pThis;
     150        AssertMsgFailed(("rtThreadCtxHookSolFree with cRefs=0 pThis=%p\n", pThis));
     151    }
     152}
     153
     154
     155RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser)
     156{
     157    /*
     158     * Validate input.
     159     */
     160    PRTTHREADCTXHOOKINT pThis;
    154161    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    155 
    156     pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis));
     162    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
     163    AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
     164
     165    /*
     166     * Allocate and initialize a new hook.
     167     */
     168    pThis = (PRTTHREADCTXHOOKINT)RTMemAllocZ(sizeof(*pThis));
    157169    if (RT_UNLIKELY(!pThis))
    158170        return VERR_NO_MEMORY;
    159     pThis->u32Magic    = RTTHREADCTXINT_MAGIC;
    160     pThis->hOwner      = RTThreadNativeSelf();
    161     pThis->fRegistered = false;
    162     pThis->cRefs       = 2;               /* One reference for the thread, one for the hook object. */
    163 
    164     /*
    165      * installctx() allocates memory and thus cannot be used in RTThreadCtxHooksRegister() which can be used
    166      * with preemption disabled. We allocate the context-hooks here and use 'fRegistered' to determine if we can
     171    pThis->u32Magic     = RTTHREADCTXHOOKINT_MAGIC;
     172    pThis->hOwner       = RTThreadNativeSelf();
     173    pThis->pfnCallback  = pfnCallback;
     174    pThis->pvUser       = pvUser;
     175    pThis->fEnabled     = false;
     176    pThis->cRefs        = 2;        /* One reference for the thread, one for the caller. */
     177
     178    /*
     179     * installctx() allocates memory and thus cannot be used in RTThreadCtxHookRegister() which can be used
     180     * with preemption disabled. We allocate the context-hooks here and use 'fEnabled' to determine if we can
    167181     * invoke the consumer's hook or not.
    168182     */
     
    171185        g_rtSolThreadCtx.Install.pfnSol_installctx_old(curthread,
    172186                                                       pThis,
    173                                                        rtThreadCtxHooksSolPreempting,
    174                                                        rtThreadCtxHooksSolResumed,
    175                                                        NULL,                          /* fork */
    176                                                        NULL,                          /* lwp_create */
    177                                                        rtThreadCtxHooksSolFree);
     187                                                       rtThreadCtxHookSolOut,   /* save */
     188                                                       rtThreadCtxHookSolIn,    /* restore */
     189                                                       NULL,                    /* fork */
     190                                                       NULL,                    /* lwp_create */
     191                                                       rtThreadCtxHookSolFree);
    178192    }
    179193    else
     
    181195        g_rtSolThreadCtx.Install.pfnSol_installctx(curthread,
    182196                                                   pThis,
    183                                                    rtThreadCtxHooksSolPreempting,
    184                                                    rtThreadCtxHooksSolResumed,
    185                                                    NULL,                              /* fork */
    186                                                    NULL,                              /* lwp_create */
    187                                                    NULL,                              /* exit */
    188                                                    rtThreadCtxHooksSolFree);
    189     }
    190 
    191     *phThreadCtx = pThis;
     197                                                   rtThreadCtxHookSolOut,       /* save */
     198                                                   rtThreadCtxHookSolIn,        /* restore */
     199                                                   NULL,                        /* fork */
     200                                                   NULL,                        /* lwp_create */
     201                                                   NULL,                        /* exit */
     202                                                   rtThreadCtxHookSolFree);
     203    }
     204
     205    *phCtxHook = pThis;
    192206    return VINF_SUCCESS;
    193207}
    194208
    195209
    196 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx)
    197 {
    198     PRTTHREADCTXINT pThis = hThreadCtx;
    199     RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX);
    200 
    201     uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
    202     Assert(cRefs < UINT32_MAX / 2);
    203     return cRefs;
    204 }
    205 
    206 
    207 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
    208 {
    209     PRTTHREADCTXINT pThis = hThreadCtx;
    210     if (pThis == NIL_RTTHREADCTX)
    211         return 0;
    212 
    213     RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX);
     210RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook)
     211{
     212    /*
     213     * Validate input, ignoring NIL.
     214     */
     215    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     216    if (pThis == NIL_RTTHREADCTXHOOK)
     217        return VINF_SUCCESS;
     218    RTTHREADCTX_VALID_RETURN_RC(hCtxHook, VERR_INVALID_HANDLE);
    214219    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    215 
    216     ASMAtomicWriteBool(&pThis->fRegistered, false);
     220    Assert(pThis->fEnabled || pThis->hOwner == RTThreadNativeSelf());
     221
     222    /*
     223     * Make sure it's disabled.
     224     */
     225    ASMAtomicWriteBool(&pThis->fEnabled, false);
     226
     227    /*
     228     * Decrement.
     229     */
    217230    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
    218 
    219231    if (   cRefs == 1
    220232        && pThis->hOwner == RTThreadNativeSelf())
    221233    {
    222234        /*
    223          * removectx() will invoke rtThreadCtxHooksSolFree() and there is no way to bypass it and still use
    224          * rtThreadCtxHooksSolFree() at the same time.  Hence the convulated reference counting.
     235         * removectx() will invoke rtThreadCtxHookSolFree() and there is no way to bypass it and still use
     236         * rtThreadCtxHookSolFree() at the same time.  Hence the convulated reference counting.
    225237         *
    226238         * When this function is called from the owner thread and is the last reference, we call removectx() which
    227          * will invoke rtThreadCtxHooksSolFree() with cRefs = 1 and that will then free the hook object.
     239         * will invoke rtThreadCtxHookSolFree() with cRefs = 1 and that will then free the hook object.
    228240         *
    229241         * When the function is called from a different thread, we simply decrement the reference. Whenever the
    230          * ring-0 thread dies, Solaris will call rtThreadCtxHooksSolFree() which will free the hook object.
     242         * ring-0 thread dies, Solaris will call rtThreadCtxHookSolFree() which will free the hook object.
    231243         */
    232244        int rc;
     
    235247            rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread,
    236248                                                              pThis,
    237                                                               rtThreadCtxHooksSolPreempting,
    238                                                               rtThreadCtxHooksSolResumed,
    239                                                               NULL,                          /* fork */
    240                                                               NULL,                          /* lwp_create */
    241                                                               rtThreadCtxHooksSolFree);
     249                                                              rtThreadCtxHookSolOut,    /* save */
     250                                                              rtThreadCtxHookSolIn,     /* restore */
     251                                                              NULL,                     /* fork */
     252                                                              NULL,                     /* lwp_create */
     253                                                              rtThreadCtxHookSolFree);
    242254        }
    243255        else
     
    245257            rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread,
    246258                                                          pThis,
    247                                                           rtThreadCtxHooksSolPreempting,
    248                                                           rtThreadCtxHooksSolResumed,
    249                                                           NULL,                              /* fork */
    250                                                           NULL,                              /* lwp_create */
    251                                                           NULL,                              /* exit */
    252                                                           rtThreadCtxHooksSolFree);
     259                                                          rtThreadCtxHookSolOut,        /* save */
     260                                                          rtThreadCtxHookSolIn,         /* restore */
     261                                                          NULL,                         /* fork */
     262                                                          NULL,                         /* lwp_create */
     263                                                          NULL,                         /* exit */
     264                                                          rtThreadCtxHookSolFree);
    253265        }
    254266        AssertMsg(rc, ("removectx() failed. rc=%d\n", rc));
     
    267279         */
    268280        Assert(pThis->hOwner != RTThreadNativeSelf());
    269         ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
     281        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXHOOKINT_MAGIC);
    270282        RTMemFree(pThis);
    271283    }
     
    275287
    276288
    277 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
     289RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook)
    278290{
    279291    /*
    280292     * Validate input.
    281293     */
    282     PRTTHREADCTXINT pThis = hThreadCtx;
    283     if (pThis == NIL_RTTHREADCTX)
    284         return VERR_INVALID_HANDLE;
     294    PRTTHREADCTXHOOKINT pThis = hCtxHook;
    285295    AssertPtr(pThis);
    286     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     296    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
    287297                    VERR_INVALID_HANDLE);
    288298    Assert(pThis->hOwner == RTThreadNativeSelf());
    289 
    290     /*
    291      * Register the callback.
    292      */
    293     pThis->pvUser           = pvUser;
    294     pThis->pfnThreadCtxHook = pfnThreadCtxHook;
    295     pThis->fRegistered      = true;
     299    Assert(!pThis->fEnabled);
     300
     301    /*
     302     * Mark it as enabled.
     303     */
     304    pThis->fEnabled = true;
    296305
    297306    return VINF_SUCCESS;
     
    299308
    300309
    301 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
     310RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook)
    302311{
    303312    /*
    304313     * Validate input.
    305314     */
    306     PRTTHREADCTXINT pThis = hThreadCtx;
    307     if (pThis == NIL_RTTHREADCTX)
    308         return VERR_INVALID_HANDLE;
    309     AssertPtr(pThis);
    310     AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
    311                     VERR_INVALID_HANDLE);
    312     Assert(pThis->hOwner == RTThreadNativeSelf());
    313     Assert(pThis->fRegistered);
    314 
    315     /*
    316      * Deregister the callback.
    317      */
    318     pThis->fRegistered = false;
     315    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     316    if (pThis != NIL_RTTHREADCTXHOOK)
     317    {
     318        AssertPtr(pThis);
     319        AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     320                        VERR_INVALID_HANDLE);
     321        Assert(pThis->hOwner == RTThreadNativeSelf());
     322
     323        /*
     324         * Mark it as disabled.
     325         */
     326        pThis->fEnabled = false;
     327    }
    319328
    320329    return VINF_SUCCESS;
     
    322331
    323332
    324 RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx)
     333RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook)
    325334{
    326335    /*
    327336     * Validate input.
    328337     */
    329     PRTTHREADCTXINT pThis = hThreadCtx;
    330     if (pThis == NIL_RTTHREADCTX)
     338    PRTTHREADCTXHOOKINT pThis = hCtxHook;
     339    if (pThis == NIL_RTTHREADCTXHOOK)
    331340        return false;
    332341    AssertPtr(pThis);
    333     AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
    334 
    335     return pThis->fRegistered;
    336 }
    337 
     342    AssertMsgReturn(pThis->u32Magic == RTTHREADCTXHOOKINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
     343                    false);
     344
     345    return pThis->fEnabled;
     346}
     347
  • trunk/src/VBox/Runtime/testcase/tstRTR0ThreadPreemption.cpp

    r54453 r55863  
    4949    RTCPUID             uSourceCpuId;
    5050    RTNATIVETHREAD      hSourceThread;
    51     RTTHREADCTX         hThreadCtx;
    5251
    5352    /* For RTTHREADCTXEVENT_PREEMPTING. */
     
    8281    switch (enmEvent)
    8382    {
    84         case RTTHREADCTXEVENT_PREEMPTING:
     83        case RTTHREADCTXEVENT_OUT:
    8584        {
    8685            ASMAtomicWriteBool(&pData->fPreemptingInvoked, true);
     
    119118        }
    120119
    121         case RTTHREADCTXEVENT_RESUMED:
     120        case RTTHREADCTXEVENT_IN:
    122121        {
    123122            ASMAtomicWriteBool(&pData->fResumedInvoked, true);
     
    302301            }
    303302
    304             bool fRegistered = RTThreadCtxHooksAreRegistered(NIL_RTTHREADCTX);
     303            bool fRegistered = RTThreadCtxHookIsEnabled(NIL_RTTHREADCTXHOOK);
    305304            if (fRegistered)
    306305            {
    307                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered returns true before creating any hooks");
    308                 break;
    309             }
    310 
    311             RTTHREADCTX hThreadCtx;
    312             int rc = RTThreadCtxHooksCreate(&hThreadCtx);
    313             if (RT_FAILURE(rc))
    314             {
    315                 if (rc == VERR_NOT_SUPPORTED)
    316                     RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED");
    317                 else
    318                     RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc);
    319                 break;
    320             }
    321 
    322             fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
    323             if (fRegistered)
    324             {
    325                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered returns true before registering any hooks");
    326                 RTThreadCtxHooksRelease(hThreadCtx);
     306                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled returns true before creating any hooks");
    327307                break;
    328308            }
     
    331311            AssertReturn(pCtxData, VERR_NO_MEMORY);
    332312            pCtxData->u32Magic           = TSTRTR0THREADCTXDATA_MAGIC;
    333             pCtxData->hThreadCtx         = hThreadCtx;
    334313            pCtxData->fPreemptingSuccess = false;
    335314            pCtxData->fPreemptingInvoked = false;
     
    339318            RT_ZERO(pCtxData->achResult);
    340319
     320            RTTHREADCTXHOOK hThreadCtx;
     321            int rc = RTThreadCtxHookCreate(&hThreadCtx, 0, tstRTR0ThreadCtxHook, pCtxData);
     322            if (RT_FAILURE(rc))
     323            {
     324                if (rc == VERR_NOT_SUPPORTED)
     325                    RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED");
     326                else
     327                    RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc);
     328                RTMemFree(pCtxData);
     329                break;
     330            }
     331
     332            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
     333            if (fRegistered)
     334            {
     335                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled returns true before registering any hooks");
     336                RTThreadCtxHookDestroy(hThreadCtx);
     337                break;
     338            }
     339
    341340            RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
    342341            RTThreadPreemptDisable(&PreemptState);
     
    345344            pCtxData->uSourceCpuId       = RTMpCpuId();
    346345
    347             rc = RTThreadCtxHooksRegister(hThreadCtx, &tstRTR0ThreadCtxHook, pCtxData);
     346            rc = RTThreadCtxHookEnable(hThreadCtx);
    348347            if (RT_FAILURE(rc))
    349348            {
    350349                RTThreadPreemptRestore(&PreemptState);
    351350                RTMemFree(pCtxData);
    352                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRegister returns %Rrc", rc);
    353                 break;
    354             }
    355 
    356             fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
     351                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookEnable returns %Rrc", rc);
     352                break;
     353            }
     354
     355            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
    357356            if (!fRegistered)
    358357            {
    359358                RTThreadPreemptRestore(&PreemptState);
    360359                RTMemFree(pCtxData);
    361                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered return false when hooks are supposedly registered");
     360                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return false when hooks are supposedly registered");
    362361                break;
    363362            }
     
    428427            }
    429428
    430             RTThreadCtxHooksDeregister(hThreadCtx);
    431 
    432             fRegistered = RTThreadCtxHooksAreRegistered(hThreadCtx);
     429            RTThreadCtxHookDisable(hThreadCtx);
     430
     431            fRegistered = RTThreadCtxHookIsEnabled(hThreadCtx);
    433432            if (fRegistered)
    434433            {
    435434                RTMemFree(pCtxData);
    436                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksAreRegistered return true when hooks are deregistered");
     435                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHookIsEnabled return true when hooks are deregistered");
    437436                break;
    438437            }
    439438
    440439            Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    441             uint32_t cRefs = RTThreadCtxHooksRelease(hThreadCtx);
    442             if (cRefs == UINT32_MAX)
    443                 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns invalid cRefs!");
     440            rc = RTThreadCtxHookDestroy(hThreadCtx);
     441            if (RT_FAILURE(rc))
     442                RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns %Rrc!", rc);
    444443
    445444            RTMemFree(pCtxData);
Note: See TracChangeset for help on using the changeset viewer.

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