VirtualBox

Changeset 40756 in vbox for trunk/src


Ignore:
Timestamp:
Apr 3, 2012 2:47:33 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
77247
Message:

SUP: Working on a generic tracer interface.

Location:
trunk/src/VBox/HostDrivers/Support
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r40614 r40756  
    4646  LIBRARIES       += SUPR0IdcClient
    4747  SYSMODS.freebsd += vboxdrv
    48   SYSMODS.linux   += vboxdrv
    4948  SYSMODS.win     += VBoxDrv
    5049  SYSMODS.os2     += VBoxDrv
     
    234233
    235234
    236 #
    237 # vboxdrv.ko - The Linux Kernel Module (syntax check only).
    238 #
    239 ifeq ($(KBUILD_TARGET),linux)
    240 vboxdrv_TEMPLATE      = VBOXR0DRV
    241 vboxdrv_DEFS          = KBUILD_MODNAME=KBUILD_STR\(vboxdrv\) KBUILD_BASENAME=KBUILD_STR\(vboxdrv\) MODULE IN_RT_R0 IN_SUP_R0 CONFIG_VBOXDRV_AS_MISC
    242 ifdef VBOX_LINUX_VERSION_2_4
    243  vboxdrv_DEFS        += EXPORT_SYMTAB
    244 endif
    245 vboxdrv_INCS         := \
    246         $(PATH_SUB_CURRENT) \
    247         $(PATH_ROOT)/src/VBox/Runtime/r0drv/linux
    248 vboxdrv_LIBS          = $(PATH_STAGE_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB)
    249 vboxdrv_LIBS.debug    = $(vboxdrv_LIBS) $(VBOX_GCC_LIBGCC)
    250 vboxdrv_SOURCES       = \
    251         $(KBUILD_TARGET)/SUPDrv-$(KBUILD_TARGET).c \
    252         SUPDrv.c \
    253         SUPDrvSem.c
    254 ifndef VBOX_LINUX_VERSION_2_4
    255  vboxdrv_SOURCES     += \
    256         $(KBUILD_TARGET)/SUPDrv-$(KBUILD_TARGET).mod.c
    257 endif
    258 
    259 
    260 #
    261 # Targets for installing the linux sources.
    262 #
    263 vboxdrv-mod_INST    = bin/src/vboxdrv/
    264 vboxdrv-mod_SOURCES = \
    265         $(subst $(DQUOTE),,$(FILES_VBOXDRV_NOBIN)) \
    266         $(vboxdrv-mod_0_OUTDIR)/Makefile
    267 vboxdrv-mod_EXEC_SOURCES  = \
    268         $(subst $(DQUOTE),,$(FILES_VBOXDRV_BIN)) \
    269         $(PATH_ROOT)/src/VBox/HostDrivers/linux/do_Module.symvers
    270 vboxdrv-mod_CLEAN   = \
    271         $(vboxdrv-mod_0_OUTDIR)/Makefile \
    272         $(PATH_TARGET)/vboxdrv-mod-1.dep \
    273 
    274 # Scripts needed for building the kernel modules
    275 
    276 includedep $(PATH_TARGET)/vboxdrv-mod-1.dep
    277 $$(vboxdrv-mod_0_OUTDIR)/Makefile: \
    278                 $(PATH_SUB_CURRENT)/linux/Makefile \
    279                 $$(if $$(eq $$(Support/linux/Makefile_VBOX_HARDENED),$$(VBOX_WITH_HARDENING)),,FORCE) \
    280                 | $$(dir $$@)
    281         $(call MSG_TOOL,Creating,,$@)
    282  ifndef VBOX_WITH_HARDENING
    283         $(QUIET)$(SED) -e "s;-DVBOX_WITH_HARDENING;;g" --output $@ $<
    284  else
    285         $(QUIET)$(CP) -f $< $@
    286  endif
    287         %$(QUIET2)$(APPEND) -t '$(PATH_TARGET)/vboxdrv-mod-1.dep' 'Support/linux/Makefile_VBOX_HARDENED=$(VBOX_WITH_HARDENING)'
    288 
    289 endif # real linux
    290 
    291 
    292235ifeq ($(KBUILD_TARGET),os2)
    293236
     
    366309# New VBoxDrv target. TODO: Convert all the above to use this!
    367310#
    368 if1of ($(KBUILD_TARGET), darwin solaris)
     311if1of ($(KBUILD_TARGET), darwin linux solaris)
    369312 # Leopard (x86) and Snow Leopard (x86/amd64)
    370313 SYSMODS += VBoxDrv
    371314 VBoxDrv_TEMPLATE         = VBOXR0DRV
     315 VBoxDrv_NAME.freebsd     = vboxdrv
     316 VBoxDrv_NAME.linux       = vboxdrv
    372317 VBoxDrv_NAME.solaris     = vboxdrv
    373  VBoxDrv_NAME.freebsd     = vboxdrv
    374318 VBoxDrv_INST.darwin      = $(INST_VBOXDRV)Contents/MacOS/
    375319 VBoxDrv_DEFS            := IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER VBOX_SVN_REV=$(VBOX_SVN_REV)
     320 ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     321  VBoxDrv_DEFS           += VBOX_WITH_SUPDRV_GENERIC_TRACER
     322 endif
    376323 ifdef VBOX_WITH_DTRACE_R0DRV
    377324  VBoxDrv_DEFS           += VBOX_WITH_DTRACE VBOX_WITH_DTRACE_R0DRV
    378325 endif
    379326 ifdef VBOX_WITH_NETFLT
    380   vboxdrv_DEFS.solaris   += VBOX_WITH_NETFLT
     327  VBoxDrv_DEFS.solaris   += VBOX_WITH_NETFLT
    381328 endif
    382329 ifdef VBOX_WITH_NATIVE_SOLARIS_LOADING
    383   vboxdrv_DEFS.solaris   += VBOX_WITH_NATIVE_SOLARIS_LOADING
    384  endif
    385  VBoxDrv_DEFS.darwin:= VBOX_WITH_HOST_VMX
     330  VBoxDrv_DEFS.solaris   += VBOX_WITH_NATIVE_SOLARIS_LOADING
     331 endif
     332 VBoxDrv_DEFS.linux      := \
     333        KBUILD_MODNAME=KBUILD_STR\(vboxdrv\) KBUILD_BASENAME=KBUILD_STR\(vboxdrv\) MODULE CONFIG_VBOXDRV_AS_MISC
     334 ifdef VBOX_LINUX_VERSION_2_4
     335  VBoxDrv_DEFS.linux     += EXPORT_SYMTAB
     336 endif
     337 VBoxDrv_DEFS.darwin     := VBOX_WITH_HOST_VMX
    386338 #VBoxDrv_DEFS.debug      += DEBUG_DARWIN_GIP
    387339 VBoxDrv_INCS             = . $(VBoxDrv_0_OUTDIR)
    388340 VBoxDrv_INCS.darwin      = ./darwin
     341 VBoxDrv_INCS.linux       = $(PATH_ROOT)/src/VBox/Runtime/r0drv/linux
    389342 VBoxDrv_LIBS             = $(PATH_STAGE_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB)
    390343 #VBoxDrv_LDFLAGS         = -v -Wl,-whyload -Wl,-v -Wl,-whatsloaded
     344 VBoxDrv_LIBS.linux.debug = $(VBoxDrv_LIBS) $(VBOX_GCC_LIBGCC)
     345
    391346 VBoxDrv_SOURCES.darwin   = darwin/SUPDrv-darwin.cpp
    392347 VBoxDrv_SOURCES.solaris  = solaris/SUPDrv-solaris.c
     
    395350        SUPDrvSem.c \
    396351        SUPDrv.d
     352 ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     353  VBoxDrv_SOURCES        += \
     354        SUPDrv-tracer.cpp
     355 endif
    397356 ifdef VBOX_WITH_DTRACE_R0DRV
    398357  VBoxDrv_SOURCES        += \
    399         SUPDrv-dtrace.cpp 
     358        SUPDrv-dtrace.cpp
    400359  VBoxDrv_DTRACE_OBJ_FLAGS.solaris = --probe-fn-name=dtrace_probe
    401360  VBoxDrv_LDFLAGS.solaris+= -N misc/dtrace
    402361 endif
    403362 VBoxDrv_LDFLAGS.solaris += -N misc/ctf
     363 ifndef VBOX_LINUX_VERSION_2_4
     364  VBoxDrv_SOURCES.linux  += \
     365        linux/SUPDrv-linux.mod.c
     366 endif
    404367endif
    405368
     
    429392endif
    430393
     394
    431395if1of ($(KBUILD_TARGET), darwin solaris)
    432396 # Common manual loader script.
     
    438402
    439403
     404if1of ($(KBUILD_TARGET), linux)
     405 #
     406 # Targets for installing the linux sources.
     407 #
     408 vboxdrv-mod_INST    = bin/src/vboxdrv/
     409 vboxdrv-mod_SOURCES = \
     410        $(subst $(DQUOTE),,$(FILES_VBOXDRV_NOBIN)) \
     411        $(vboxdrv-mod_0_OUTDIR)/Makefile
     412 vboxdrv-mod_EXEC_SOURCES  = \
     413        $(subst $(DQUOTE),,$(FILES_VBOXDRV_BIN)) \
     414        $(PATH_ROOT)/src/VBox/HostDrivers/linux/do_Module.symvers
     415 vboxdrv-mod_CLEAN   = \
     416        $(vboxdrv-mod_0_OUTDIR)/Makefile \
     417        $(PATH_TARGET)/vboxdrv-mod-1.dep \
     418
     419 # Scripts needed for building the kernel modules
     420 includedep $(PATH_TARGET)/vboxdrv-mod-1.dep
     421 $$(vboxdrv-mod_0_OUTDIR)/Makefile: \
     422                $(PATH_SUB_CURRENT)/linux/Makefile \
     423                $$(if $$(eq $$(Support/linux/Makefile_VBOX_HARDENED),$$(VBOX_WITH_HARDENING)),,FORCE) \
     424                | $$(dir $$@)
     425        $(call MSG_TOOL,Creating,,$@)
     426 ifndef VBOX_WITH_HARDENING
     427        $(QUIET)$(SED) -e "s;-DVBOX_WITH_HARDENING;;g" --output $@ $<
     428 else
     429        $(QUIET)$(CP) -f $< $@
     430 endif
     431        %$(QUIET2)$(APPEND) -t '$(PATH_TARGET)/vboxdrv-mod-1.dep' 'Support/linux/Makefile_VBOX_HARDENED=$(VBOX_WITH_HARDENING)'
     432endif # real linux
     433
     434
    440435endif # !VBOX_ONLY_DOCS && !VBOX_ONLY_EXTPACKS && !VBOX_ONLY_TESTSUITE
    441436include $(KBUILD_PATH)/subfooter.kmk
  • trunk/src/VBox/HostDrivers/Support/SUPDrv-dtrace.cpp

    r40704 r40756  
    393393
    394394/**
    395  * Frees the provider structure and associated resources. 
    396  * 
     395 * Frees the provider structure and associated resources.
     396 *
    397397 * @param   pProv               The provider to free.
    398398 */
     
    408408
    409409/**
    410  * Deregisters a provider. 
    411  * 
     410 * Deregisters a provider.
     411 *
    412412 * If the provider is still busy, it will be put in the zombie list.
    413  * 
     413 *
    414414 * @param   pDevExt             The device extension.
    415  * @param   pProv               The provider. 
    416  * 
    417  * @remarks The caller owns mtxDTrace. 
     415 * @param   pProv               The provider.
     416 *
     417 * @remarks The caller owns mtxDTrace.
    418418 */
    419419static void supdrvVtgDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVDTPROVIDER pProv)
     
    436436
    437437/**
    438  * Processes the zombie list. 
    439  * 
     438 * Processes the zombie list.
     439 *
    440440 * @param   pDevExt             The device extension.
    441441 */
     
    469469 * @param   pszModName          The module name.
    470470 */
    471 static int supdrvVtgRegister(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage, 
     471static int supdrvVtgRegister(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
    472472                             PSUPDRVSESSION pSession, const char *pszModName)
    473473{
     
    502502            break;
    503503        }
    504         if (   pProv->pSession == pSession 
     504        if (   pProv->pSession == pSession
    505505            && pProv->pImage   == pImage)
    506506        {
     
    653653
    654654/**
    655  * Registers the VTG tracepoint providers of a module loaded by 
    656  * the support driver. 
    657  * 
     655 * Registers the VTG tracepoint providers of a module loaded by
     656 * the support driver.
     657 *
    658658 * This should be called from the ModuleInit code.
    659659 *
     
    669669    int             rc;
    670670
    671     /* 
     671    /*
    672672     * Validate input and context.
    673673     */
     
    684684     */
    685685    cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
    686     AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits, 
     686    AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
    687687                    ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
    688688                    VERR_INVALID_PARAMETER);
     
    701701
    702702/**
    703  * Module unloading hook, called after execution in the module have ceased. 
    704  *
    705  * @param   pDevExt             The device extension structure. 
    706  * @param   pImage              The image being unloaded. 
     703 * Module unloading hook, called after execution in the module have ceased.
     704 *
     705 * @param   pDevExt             The device extension structure.
     706 * @param   pImage              The image being unloaded.
    707707 */
    708708void VBOXCALL supdrvVtgModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
     
    735735 *
    736736 * @returns VBox status code.
    737  * @param   pDevExt             The device extension structure. 
    738  * @param   pVtgFireProbe       Pointer to the SUPR0VtgFireProbe entry. 
     737 * @param   pDevExt             The device extension structure.
     738 * @param   pVtgFireProbe       Pointer to the SUPR0VtgFireProbe entry.
    739739 */
    740740int VBOXCALL supdrvVtgInit(PSUPDRVDEVEXT pDevExt, PSUPFUNC pVtgFireProbe)
     
    986986{
    987987    PSUPDRVDTPROVIDER   pProv      = (PSUPDRVDTPROVIDER)pvProv;
    988     unsigned            uArg       = pArgDesc->dtargd_ndx; 
     988    unsigned            uArg       = pArgDesc->dtargd_ndx;
    989989
    990990    if (!pProv->fZombie)
     
    10151015
    10161016# ifdef __cplusplus
    1017 extern "C" 
     1017extern "C"
    10181018#endif
    10191019uint64_t dtrace_getarg(int iArg, int cFrames);
     
    10281028       cFrames argument than dtrace_caller() and/or dtrace_getpcstack(), at
    10291029       least when the probe is fired by dtrace_probe() the way we do.
    1030      
     1030
    10311031       Setting aframes to 1 when calling dtrace_probe_create gives me the right
    10321032       arguments, but the wrong 'caller'.  Since I cannot do anything about
    10331033       'caller', the only solution is this hack.
    1034      
     1034
    10351035       Not sure why the Solaris guys hasn't seen this issue before, but maybe
    10361036       there isn't anyone using the default argument getter path for ring-0
    10371037       dtrace_probe() calls, SDT surely isn't.
    1038      
     1038
    10391039       WARNING! This code is subject to dtrace_getarg interface unstability! */
    10401040    /** @todo File a solaris bug on dtrace_probe() + dtrace_getarg(). */
  • trunk/src/VBox/HostDrivers/Support/SUPDrv-tracer.cpp

    r40753 r40756  
    11/* $Id$ */
    22/** @file
    3  * VBoxDrv - The VirtualBox Support Driver - DTrace Provider.
     3 * VBoxDrv - The VirtualBox Support Driver - Generic Tracer Interface.
    44 */
    55
     
    3030*******************************************************************************/
    3131#define LOG_GROUP LOG_GROUP_SUP_DRV
     32#define SUPDRV_AGNOSTIC
    3233#include "SUPDrvInternal.h"
    3334
     
    4344#include <iprt/thread.h>
    4445
    45 #ifdef RT_OS_DARWIN /** @todo figure this! */
    46 # include "/Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/dtrace.h"
    47 #else
    48 # include <sys/dtrace.h>
    49 #endif
    50 
    5146
    5247/*******************************************************************************
     
    5449*******************************************************************************/
    5550/**
    56  * Data for a provider.
    57  */
    58 typedef struct SUPDRVDTPROVIDER
     51 * Data for a tracepoint provider.
     52 */
     53typedef struct SUPDRVTPPROVIDER
    5954{
    6055    /** The entry in the provider list for this image. */
    61     RTLISTNODE          ListEntry;
    62 
    63     /** The provider descriptor. */
    64     PVTGDESCPROVIDER    pDesc;
    65     /** The VTG header. */
    66     PVTGOBJHDR          pHdr;
     56    RTLISTNODE              ListEntry;
     57
     58    /** The core structure. */
     59    SUPDRVVDTPROVIDERCORE   Core;
    6760
    6861    /** Pointer to the image this provider resides in.  NULL if it's a
    6962     * driver. */
    70     PSUPDRVLDRIMAGE     pImage;
     63    PSUPDRVLDRIMAGE         pImage;
    7164    /** The session this provider is associated with if registered via
    7265     * SUPR0VtgRegisterDrv.  NULL if pImage is set. */
    73     PSUPDRVSESSION      pSession;
     66    PSUPDRVSESSION          pSession;
    7467    /** The module name. */
    75     const char         *pszModName;
    76 
    77     /** Dtrace provider attributes. */
    78     dtrace_pattr_t      DtAttrs;
    79     /** The ID of this provider. */
    80     dtrace_provider_id_t idDtProv;
    81     /** The number of probes we've provided to DTrace. */
    82     uint32_t            cProvidedProbes;
     68    const char             *pszModName;
     69
    8370    /** Set when the module is unloaded or the driver deregisters its probes. */
    84     bool                fZombie;
     71    bool                    fZombie;
     72    /** Set if the provider has been successfully registered with the
     73     *  tracer. */
     74    bool                    fRegistered;
    8575    /** The provider name (for logging purposes). */
    86     char                szName[1];
    87 } SUPDRVDTPROVIDER;
    88 /** Pointer to the data for a provider. */
    89 typedef SUPDRVDTPROVIDER *PSUPDRVDTPROVIDER;
    90 
    91 /* Seems there is some return code difference here. Keep the return code and
    92    case it to whatever the host desires. */
    93 #ifdef RT_OS_DARWIN
    94 typedef void FNPOPS_ENABLE(void *, dtrace_id_t, void *);
    95 #else
    96 typedef int  FNPOPS_ENABLE(void *, dtrace_id_t, void *);
    97 #endif
     76    char                    szName[1];
     77} SUPDRVTPPROVIDER;
     78/** Pointer to the data for a tracepoint provider. */
     79typedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER;
    9880
    9981
     
    10284*******************************************************************************/
    10385#if 0
    104 # define LOG_DTRACE(a_Args)  SUPR0Printf a_Args
     86# define LOG_TRACER(a_Args)  SUPR0Printf a_Args
    10587#else
    106 # define LOG_DTRACE(a_Args)  do { } while (0)
     88# define LOG_TRACER(a_Args)  do { } while (0)
    10789#endif
    108 
    109 /*******************************************************************************
    110 *   Internal Functions                                                         *
    111 *******************************************************************************/
    112 static void     supdrvDTracePOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc);
    113 static int      supdrvDTracePOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe);
    114 static void     supdrvDTracePOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe);
    115 static void     supdrvDTracePOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
    116                                             dtrace_argdesc_t *pArgDesc);
    117 #ifdef RT_OS_SOLARIS
    118 static uint64_t supdrvDTracePOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
    119                                            int iArg, int cFrames);
    120 #endif
    121 static void     supdrvDTracePOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe);
    122 
    12390
    12491
     
    12693*   Global Variables                                                           *
    12794*******************************************************************************/
    128 /**
    129  * DTrace provider method table.
    130  */
    131 static const dtrace_pops_t g_SupDrvDTraceProvOps =
    132 {
    133     /* .dtps_provide         = */ supdrvDTracePOps_Provide,
    134     /* .dtps_provide_module  = */ NULL,
    135     /* .dtps_enable          = */ (FNPOPS_ENABLE *)supdrvDTracePOps_Enable,
    136     /* .dtps_disable         = */ supdrvDTracePOps_Disable,
    137     /* .dtps_suspend         = */ NULL,
    138     /* .dtps_resume          = */ NULL,
    139     /* .dtps_getargdesc      = */ supdrvDTracePOps_GetArgDesc,
    140 #ifdef RT_OS_SOLARIS
    141     /* .dtps_getargval       = */ supdrvDTracePOps_GetArgVal,
    142 #else
    143     /* .dtps_getargval       = */ NULL/*supdrvDTracePOps_GetArgVal*/,
    144 #endif
    145     /* .dtps_usermode        = */ NULL,
    146     /* .dtps_destroy         = */ supdrvDTracePOps_Destroy
    147 };
    14895
    14996
     
    366313
    367314/**
    368  * Converts an attribute from VTG description speak to DTrace.
    369  *
    370  * @param   pDtAttr             The DTrace attribute (dst).
    371  * @param   pVtgAttr            The VTG attribute descriptor (src).
    372  */
    373 static void supdrvVtgConvAttr(dtrace_attribute_t *pDtAttr, PCVTGDESCATTR pVtgAttr)
    374 {
    375     pDtAttr->dtat_name  = pVtgAttr->u8Code - 1;
    376     pDtAttr->dtat_data  = pVtgAttr->u8Data - 1;
    377     pDtAttr->dtat_class = pVtgAttr->u8DataDep - 1;
    378 }
    379 
    380 /**
    381315 * Gets a string from the string table.
    382316 *
     
    393327
    394328/**
    395  * Frees the provider structure and associated resources. 
    396  * 
     329 * Frees the provider structure and associated resources.
     330 *
    397331 * @param   pProv               The provider to free.
    398332 */
    399 static void supdrvVtgFreeProvider(PSUPDRVDTPROVIDER pProv)
    400 {
    401     LOG_DTRACE(("Freeing DTrace provider '%s' / %p\n", pProv->szName, pProv->idDtProv));
     333static void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
     334{
     335    LOG_TRACER(("Freeing DTrace provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
     336    pProv->fRegistered = false;
     337    pProv->fZombie     = true;
     338    pProv->Core.pDesc  = NULL;
     339    pProv->Core.pHdr   = NULL;
     340    RT_ZERO(pProv->Core.TracerData);
     341    RTMemFree(pProv);
     342}
     343
     344
     345/**
     346 * Deregisters a provider.
     347 *
     348 * If the provider is still busy, it will be put in the zombie list.
     349 *
     350 * @param   pDevExt             The device extension.
     351 * @param   pProv               The provider.
     352 *
     353 * @remarks The caller owns mtxTracer.
     354 */
     355static void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
     356{
     357    int rc;
     358    if (!pProv->fRegistered || !pDevExt->pTracerOps)
     359        rc = VINF_SUCCESS;
     360    else
     361        rc = pDevExt->pTracerOps->pfnDeregisterProvider(pDevExt->pTracerOps, &pProv->Core);
     362    if (RT_SUCCESS(rc))
     363    {
     364        supdrvTracerFreeProvider(pProv);
     365        return;
     366    }
     367
    402368    pProv->fZombie = true;
    403     pProv->pDesc   = NULL;
    404     pProv->pHdr    = NULL;
    405     RTMemFree(pProv);
    406 }
    407 
    408 
    409 /**
    410  * Deregisters a provider.
    411  * 
    412  * If the provider is still busy, it will be put in the zombie list.
    413  * 
     369    RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
     370    LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
     371                pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
     372}
     373
     374
     375/**
     376 * Processes the zombie list.
     377 *
    414378 * @param   pDevExt             The device extension.
    415  * @param   pProv               The provider.
    416  * 
    417  * @remarks The caller owns mtxDTrace.
    418  */
    419 static void supdrvVtgDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVDTPROVIDER pProv)
    420 {
    421     int rc;
    422 
    423     dtrace_invalidate(pProv->idDtProv);
    424     rc = dtrace_unregister(pProv->idDtProv);
    425     if (!rc)
    426     {
    427         supdrvVtgFreeProvider(pProv);
    428         return;
    429     }
    430 
    431     pProv->fZombie = true;
    432     RTListAppend(&pDevExt->DtProviderZombieList, &pProv->ListEntry);
    433     LOG_DTRACE(("Invalidate DTrace provider '%s' / %p and put it on the zombie list\n", pProv->szName, pProv->idDtProv));
    434 }
    435 
    436 
    437 /**
    438  * Processes the zombie list.
    439  * 
     379 */
     380static void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
     381{
     382    PSUPDRVTPPROVIDER pProv, pProvNext;
     383
     384    RTSemFastMutexRequest(pDevExt->mtxTracer);
     385    RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
     386    {
     387        int rc = pDevExt->pTracerOps->pfnDeregisterZombieProvider(pDevExt->pTracerOps, &pProv->Core);
     388        if (RT_SUCCESS(rc))
     389        {
     390            RTListNodeRemove(&pProv->ListEntry);
     391            supdrvTracerFreeProvider(pProv);
     392        }
     393    }
     394    RTSemFastMutexRelease(pDevExt->mtxTracer);
     395}
     396
     397
     398/**
     399 * Unregisters all providers, including zombies, waiting for busy providers to
     400 * go idle and unregister smoothly.
     401 *
     402 * This may block.
     403 *
    440404 * @param   pDevExt             The device extension.
    441405 */
    442 static void supdrvVtgProcessZombies(PSUPDRVDEVEXT pDevExt)
    443 {
    444     PSUPDRVDTPROVIDER pProv, pProvNext;
    445 
    446     RTSemFastMutexRequest(pDevExt->mtxDTrace);
    447     RTListForEachSafe(&pDevExt->DtProviderZombieList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
    448     {
    449         int rc = dtrace_unregister(pProv->idDtProv);
    450         if (!rc)
    451         {
    452             RTListNodeRemove(&pProv->ListEntry);
    453             supdrvVtgFreeProvider(pProv);
    454         }
    455     }
    456     RTSemFastMutexRelease(pDevExt->mtxDTrace);
     406static void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
     407{
     408    uint32_t            i;
     409    PSUPDRVTPPROVIDER   pProv;
     410    PSUPDRVTPPROVIDER   pProvNext;
     411
     412    /*
     413     * Unregister all probes (there should only be one).
     414     */
     415    RTSemFastMutexRequest(pDevExt->mtxTracer);
     416    RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
     417    {
     418        RTListNodeRemove(&pProv->ListEntry);
     419        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     420    }
     421    RTSemFastMutexRelease(pDevExt->mtxTracer);
     422
     423    /*
     424     * Try unregister zombies now, sleep on busy ones.
     425     */
     426    for (i = 0; ; i++)
     427    {
     428        bool fEmpty;
     429
     430        RTSemFastMutexRequest(pDevExt->mtxTracer);
     431        RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
     432        {
     433            int rc;
     434            LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
     435                        pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
     436
     437            if (pDevExt->pTracerOps)
     438                rc = pDevExt->pTracerOps->pfnDeregisterZombieProvider(pDevExt->pTracerOps, &pProv->Core);
     439            else
     440                rc = VINF_SUCCESS;
     441            if (!rc)
     442            {
     443                RTListNodeRemove(&pProv->ListEntry);
     444                supdrvTracerFreeProvider(pProv);
     445            }
     446            else if (!(i & 0xf))
     447                SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n",
     448                            pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
     449            else
     450                LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
     451                            pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
     452        }
     453
     454        fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
     455        RTSemFastMutexRelease(pDevExt->mtxTracer);
     456        if (fEmpty)
     457            break;
     458
     459        /* Delay...*/
     460        RTThreadSleep(1000);
     461    }
    457462}
    458463
     
    469474 * @param   pszModName          The module name.
    470475 */
    471 static int supdrvVtgRegister(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
    472                              PSUPDRVSESSION pSession, const char *pszModName)
     476static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
     477                                      PSUPDRVSESSION pSession, const char *pszModName)
    473478{
    474479    int                 rc;
    475480    unsigned            i;
    476     PSUPDRVDTPROVIDER   pProv;
     481    PSUPDRVTPPROVIDER   pProv;
    477482
    478483    /*
     
    492497        return rc;
    493498
    494     rc = RTSemFastMutexRequest(pDevExt->mtxDTrace);
     499    rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
    495500    if (RT_FAILURE(rc))
    496501        return rc;
    497     RTListForEach(&pDevExt->DtProviderList, pProv, SUPDRVDTPROVIDER, ListEntry)
    498     {
    499         if (pProv->pHdr == pVtgHdr)
     502    RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
     503    {
     504        if (pProv->Core.pHdr == pVtgHdr)
    500505        {
    501506            rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
    502507            break;
    503508        }
    504         if (   pProv->pSession == pSession 
     509        if (   pProv->pSession == pSession
    505510            && pProv->pImage   == pImage)
    506511        {
     
    509514        }
    510515    }
    511     RTSemFastMutexRelease(pDevExt->mtxDTrace);
     516    RTSemFastMutexRelease(pDevExt->mtxTracer);
    512517    if (RT_FAILURE(rc))
    513518        return rc;
     
    522527        const char      *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
    523528        size_t const     cchName = strlen(pszName);
    524         pProv = (PSUPDRVDTPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVDTPROVIDER, szName[cchName + 1]));
     529        pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
    525530        if (pProv)
    526531        {
    527             pProv->pDesc            = pDesc;
    528             pProv->pHdr             = pVtgHdr;
     532            pProv->Core.pDesc       = pDesc;
     533            pProv->Core.pHdr        = pVtgHdr;
     534            pProv->Core.pszName     = &pProv->szName[0];
    529535            pProv->pImage           = pImage;
    530536            pProv->pSession         = pSession;
    531537            pProv->pszModName       = pszModName;
    532             pProv->idDtProv         = 0;
    533             pProv->cProvidedProbes  = 0;
    534538            pProv->fZombie          = false;
    535             memcpy(pProv->szName, pszName, cchName + 1);
    536             supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_provider, &pDesc->AttrSelf);
    537             supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_mod,      &pDesc->AttrModules);
    538             supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_func,     &pDesc->AttrFunctions);
    539             supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_name,     &pDesc->AttrNames);
    540             supdrvVtgConvAttr(&pProv->DtAttrs.dtpa_args,     &pDesc->AttrArguments);
    541 
    542             rc = dtrace_register(pProv->szName,
    543                                  &pProv->DtAttrs,
    544                                  DTRACE_PRIV_KERNEL,
    545                                  NULL /* cred */,
    546                                  &g_SupDrvDTraceProvOps,
    547                                  pProv,
    548                                  &pProv->idDtProv);
    549             if (!rc)
     539            pProv->fRegistered      = true;
     540            memcpy(&pProv->szName[0], pszName, cchName + 1);
     541
     542            rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     543            if (RT_SUCCESS(rc))
    550544            {
    551                 rc = RTSemFastMutexRequest(pDevExt->mtxDTrace);
     545                if (pDevExt->pTracerOps)
     546                    rc = pDevExt->pTracerOps->pfnRegisterProvider(pDevExt->pTracerOps, &pProv->Core);
     547                else
     548                {
     549                    pProv->fRegistered = false;
     550                    rc = VINF_SUCCESS;
     551                }
    552552                if (RT_SUCCESS(rc))
    553553                {
    554                     RTListAppend(&pDevExt->DtProviderList, &pProv->ListEntry);
    555                     RTSemFastMutexRelease(pDevExt->mtxDTrace);
    556                     LOG_DTRACE(("Registered DTrace provider '%s' in '%s' -> %p\n", pProv->szName, pszModName, pProv->idDtProv));
     554                    RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
     555                    RTSemFastMutexRelease(pDevExt->mtxTracer);
     556                    LOG_TRACER(("Registered DTrace provider '%s' in '%s' -> %p\n",
     557                                pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
    557558                }
    558559                else
    559                     dtrace_unregister(pProv->idDtProv);
     560                {
     561                    RTSemFastMutexRelease(pDevExt->mtxTracer);
     562                    RTMemFree(pProv);
     563                }
    560564            }
    561             else
    562                 rc = RTErrConvertFromErrno(rc);
    563565        }
    564566        else
     
    567569        if (RT_FAILURE(rc))
    568570        {
    569             PSUPDRVDTPROVIDER   pProvNext;
    570             supdrvVtgFreeProvider(pProv);
    571 
    572             RTSemFastMutexRequest(pDevExt->mtxDTrace);
    573             RTListForEachReverseSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
     571            PSUPDRVTPPROVIDER   pProvNext;
     572            supdrvTracerFreeProvider(pProv);
     573
     574            RTSemFastMutexRequest(pDevExt->mtxTracer);
     575            RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    574576            {
    575                 if (pProv->pHdr == pVtgHdr)
     577                if (pProv->Core.pHdr == pVtgHdr)
    576578                {
    577579                    RTListNodeRemove(&pProv->ListEntry);
    578                     supdrvVtgDeregister(pDevExt, pProv);
     580                    supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    579581                }
    580582            }
    581             RTSemFastMutexRelease(pDevExt->mtxDTrace);
     583            RTSemFastMutexRelease(pDevExt->mtxTracer);
    582584            return rc;
    583585        }
     
    605607    AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
    606608
    607     rc = supdrvVtgRegister(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
     609    rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
    608610
    609611    /*
    610612     * Try unregister zombies while we have a chance.
    611613     */
    612     supdrvVtgProcessZombies(pSession->pDevExt);
     614    supdrvTracerProcessZombies(pSession->pDevExt);
    613615
    614616    return rc;
     
    624626SUPR0DECL(void) SUPR0VtgDeregisterDrv(PSUPDRVSESSION pSession)
    625627{
    626     PSUPDRVDTPROVIDER pProv, pProvNext;
     628    PSUPDRVTPPROVIDER pProv, pProvNext;
    627629    PSUPDRVDEVEXT     pDevExt;
    628630    AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
     
    634636     * Search for providers belonging to this driver session.
    635637     */
    636     RTSemFastMutexRequest(pDevExt->mtxDTrace);
    637     RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
     638    RTSemFastMutexRequest(pDevExt->mtxTracer);
     639    RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    638640    {
    639641        if (pProv->pSession == pSession)
    640642        {
    641643            RTListNodeRemove(&pProv->ListEntry);
    642             supdrvVtgDeregister(pDevExt, pProv);
    643         }
    644     }
    645     RTSemFastMutexRelease(pDevExt->mtxDTrace);
     644            supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     645        }
     646    }
     647    RTSemFastMutexRelease(pDevExt->mtxTracer);
    646648
    647649    /*
    648650     * Try unregister zombies while we have a chance.
    649651     */
    650     supdrvVtgProcessZombies(pDevExt);
    651 }
    652 
    653 
    654 /**
    655  * Registers the VTG tracepoint providers of a module loaded by 
    656  * the support driver. 
    657  * 
     652    supdrvTracerProcessZombies(pDevExt);
     653}
     654
     655
     656/**
     657 * Registers the VTG tracepoint providers of a module loaded by
     658 * the support driver.
     659 *
    658660 * This should be called from the ModuleInit code.
    659661 *
     
    669671    int             rc;
    670672
    671     /* 
     673    /*
    672674     * Validate input and context.
    673675     */
     
    675677    AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
    676678
     679    AssertPtrReturn(pImage, VERR_INVALID_POINTER);
    677680    pDevExt = pImage->pDevExt;
    678681    AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
     
    684687     */
    685688    cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
    686     AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits, 
     689    AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
    687690                    ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
    688691                    VERR_INVALID_PARAMETER);
    689692    cbVtgObj = pImage->cbImageBits - cbVtgObj;
    690693
    691     rc = supdrvVtgRegister(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
     694    rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
    692695
    693696    /*
    694697     * Try unregister zombies while we have a chance.
    695698     */
    696     supdrvVtgProcessZombies(pDevExt);
     699    supdrvTracerProcessZombies(pDevExt);
    697700
    698701    return rc;
     
    701704
    702705/**
    703  * Module unloading hook, called after execution in the module have ceased.
    704  *
    705  * @param   pDevExt             The device extension structure.
    706  * @param   pImage              The image being unloaded.
    707  */
    708 void VBOXCALL supdrvVtgModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
    709 {
    710     PSUPDRVDTPROVIDER pProv, pProvNext;
    711 
    712     /*
    713      * Unregister all providers belonging to this image.
    714      */
    715     RTSemFastMutexRequest(pDevExt->mtxDTrace);
    716     RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
    717     {
    718         if (pProv->pImage == pImage)
    719         {
    720             RTListNodeRemove(&pProv->ListEntry);
    721             supdrvVtgDeregister(pDevExt, pProv);
    722         }
    723     }
    724     RTSemFastMutexRelease(pDevExt->mtxDTrace);
    725 
    726     /*
    727      * Try unregister zombies while we have a chance.
    728      */
    729     supdrvVtgProcessZombies(pDevExt);
     706 * Registers the tracer.
     707 *
     708 * This should be called from the ModuleInit code or from a ring-0 session.
     709 *
     710 * @returns VBox status code.
     711 * @param   hMod                The module handle.
     712 * @param   pSession            Ring-0 session handle.
     713 * @param   pReg                Pointer to the tracer registration structure.
     714 * @param   ppHlp               Where to return the tracer helper method table.
     715 */
     716SUPR0DECL(int) SUPR0TracerRegister(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
     717{
     718    PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
     719    PSUPDRVDEVEXT   pDevExt;
     720    int             rc;
     721
     722    /*
     723     * Validate input and context.
     724     */
     725    AssertPtrReturn(ppHlp, VERR_INVALID_POINTER);
     726    *ppHlp = NULL;
     727    AssertPtrReturn(pReg,  VERR_INVALID_HANDLE);
     728
     729    if (pImage)
     730    {
     731        AssertPtrReturn(pImage, VERR_INVALID_POINTER);
     732        AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
     733        pDevExt = pImage->pDevExt;
     734        AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
     735        AssertReturn(pDevExt->pLdrInitImage  == pImage, VERR_WRONG_ORDER);
     736        AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
     737    }
     738    else
     739    {
     740        AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
     741        AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
     742        pDevExt = pSession->pDevExt;
     743        AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
     744    }
     745
     746    AssertPtrReturn(pReg->pfnRegisterProvider, VERR_INVALID_POINTER);
     747    AssertPtrReturn(pReg->pfnDeregisterProvider, VERR_INVALID_POINTER);
     748    AssertPtrReturn(pReg->pfnDeregisterZombieProvider, VERR_INVALID_POINTER);
     749
     750    /*
     751     * Do the job.
     752     */
     753    rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     754    if (RT_SUCCESS(rc))
     755    {
     756        if (!pDevExt->pTracerOps)
     757        {
     758            pDevExt->pTracerOps     = pReg;
     759            pDevExt->pTracerSession = pSession;
     760            pDevExt->pTracerImage   = pImage;
     761
     762            *ppHlp = &pDevExt->TracerHlp;
     763            rc = VINF_SUCCESS;
     764        }
     765        else
     766            rc = VERR_SUPDRV_TRACER_ALREADY_REGISTERED;
     767        RTSemFastMutexRelease(pDevExt->mtxTracer);
     768    }
     769
     770    return rc;
     771
     772}
     773
     774
     775/**
     776 * Deregister a tracer associated with a ring-0 session.
     777 *
     778 * @returns VBox status code.
     779 * @param   pSession            Ring-0 session handle.
     780 */
     781SUPR0DECL(int) SUPR0TracerDeregister(PSUPDRVSESSION pSession)
     782{
     783    PSUPDRVDEVEXT   pDevExt;
     784    int             rc;
     785
     786    /*
     787     * Validate input and context.
     788     */
     789    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
     790    AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
     791    pDevExt = pSession->pDevExt;
     792    AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
     793
     794    /*
     795     * Do the job.
     796     */
     797    rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     798    if (RT_SUCCESS(rc))
     799    {
     800        if (pDevExt->pTracerSession == pSession)
     801        {
     802            pDevExt->fTracerUnloading = true;
     803            RTSemFastMutexRelease(pDevExt->mtxTracer);
     804
     805            supdrvTracerRemoveAllProviders(pDevExt);
     806
     807            RTSemFastMutexRequest(pDevExt->mtxTracer);
     808            pDevExt->pTracerImage     = NULL;
     809            pDevExt->pTracerSession   = NULL;
     810            pDevExt->pTracerOps       = NULL;
     811            pDevExt->fTracerUnloading = false;
     812        }
     813        else
     814            rc = VERR_SUPDRV_TRACER_NOT_REGISTERED;
     815        RTSemFastMutexRelease(pDevExt->mtxTracer);
     816    }
     817
     818    return rc;
     819}
     820
     821
     822/**
     823 * Module unloading hook, called after execution in the module have ceased.
     824 *
     825 * @param   pDevExt             The device extension structure.
     826 * @param   pImage              The image being unloaded.
     827 */
     828void VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
     829{
     830    PSUPDRVTPPROVIDER pProv, pProvNext;
     831    AssertPtrReturnVoid(pImage);        /* paranoia */
     832
     833    RTSemFastMutexRequest(pDevExt->mtxTracer);
     834
     835    /*
     836     * If it is the tracer image, we have to unload all the providers.
     837     */
     838    if (pDevExt->pTracerImage == pImage)
     839    {
     840        pDevExt->fTracerUnloading = true;
     841        RTSemFastMutexRelease(pDevExt->mtxTracer);
     842
     843        supdrvTracerRemoveAllProviders(pDevExt);
     844
     845        RTSemFastMutexRequest(pDevExt->mtxTracer);
     846        pDevExt->pTracerImage     = NULL;
     847        pDevExt->pTracerSession   = NULL;
     848        pDevExt->pTracerOps       = NULL;
     849        pDevExt->fTracerUnloading = false;
     850        RTSemFastMutexRelease(pDevExt->mtxTracer);
     851    }
     852    else
     853    {
     854        /*
     855         * Unregister all providers belonging to this image.
     856         */
     857        RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
     858        {
     859            if (pProv->pImage == pImage)
     860            {
     861                RTListNodeRemove(&pProv->ListEntry);
     862                supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     863            }
     864        }
     865
     866        RTSemFastMutexRelease(pDevExt->mtxTracer);
     867
     868        /*
     869         * Try unregister zombies while we have a chance.
     870         */
     871        supdrvTracerProcessZombies(pDevExt);
     872    }
    730873}
    731874
     
    735878 *
    736879 * @returns VBox status code.
    737  * @param   pDevExt             The device extension structure.
    738  * @param   pVtgFireProbe       Pointer to the SUPR0VtgFireProbe entry.
    739  */
    740 int VBOXCALL supdrvVtgInit(PSUPDRVDEVEXT pDevExt, PSUPFUNC pVtgFireProbe)
    741 {
    742     Assert(!strcmp(pVtgFireProbe->szName, "SUPR0VtgFireProbe"));
    743 
     880 * @param   pDevExt             The device extension structure.
     881 */
     882int VBOXCALL supdrvTracerInit(PSUPDRVDEVEXT pDevExt)
     883{
    744884    /*
    745885     * Register a provider for this module.
    746886     */
    747     int rc = RTSemFastMutexCreate(&pDevExt->mtxDTrace);
     887    int rc = RTSemFastMutexCreate(&pDevExt->mtxTracer);
    748888    if (RT_SUCCESS(rc))
    749889    {
    750 #ifdef RT_OS_SOLARIS
    751         pVtgFireProbe->pfn = (void *)(uintptr_t)dtrace_probe;
    752 #endif
    753         RTListInit(&pDevExt->DtProviderList);
    754         RTListInit(&pDevExt->DtProviderZombieList);
    755         rc = supdrvVtgRegister(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
     890        pDevExt->TracerHlp.uVersion    = SUPDRVTRACERHLP_VERSION;
     891        /** @todo  */
     892        pDevExt->TracerHlp.uEndVersion = SUPDRVTRACERHLP_VERSION;
     893
     894        RTListInit(&pDevExt->TracerProviderList);
     895        RTListInit(&pDevExt->TracerProviderZombieList);
     896        rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
    756897        if (RT_SUCCESS(rc))
    757898            return rc;
    758         RTSemFastMutexDestroy(pDevExt->mtxDTrace);
    759     }
    760     pDevExt->mtxDTrace = NIL_RTSEMFASTMUTEX;
     899        RTSemFastMutexDestroy(pDevExt->mtxTracer);
     900    }
     901    pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
    761902    return rc;
    762903}
     
    769910 * @param   pDevExt             The device extension structure.
    770911 */
    771 void VBOXCALL supdrvVtgTerm(PSUPDRVDEVEXT pDevExt)
    772 {
    773     PSUPDRVDTPROVIDER pProv, pProvNext;
    774     uint32_t i;
    775     LOG_DTRACE(("supdrvVtgTerm\n"));
    776 
    777     /*
    778      * Unregister all probes (there should only be one).
    779      */
    780     RTSemFastMutexRequest(pDevExt->mtxDTrace);
    781     RTListForEachSafe(&pDevExt->DtProviderList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
    782     {
    783         RTListNodeRemove(&pProv->ListEntry);
    784         supdrvVtgDeregister(pDevExt, pProv);
    785     }
    786     RTSemFastMutexRelease(pDevExt->mtxDTrace);
    787 
    788     /*
    789      * Try unregister zombies now, sleep on busy ones.
    790      */
    791     for (i = 0; ; i++)
    792     {
    793         bool fEmpty;
    794 
    795         RTSemFastMutexRequest(pDevExt->mtxDTrace);
    796         RTListForEachSafe(&pDevExt->DtProviderZombieList, pProv, pProvNext, SUPDRVDTPROVIDER, ListEntry)
    797         {
    798             int rc;
    799             LOG_DTRACE(("supdrvVtgTerm: Attemting to unregister '%s' / %p...\n", pProv->szName, pProv->idDtProv));
    800             rc = dtrace_unregister(pProv->idDtProv);
    801             if (!rc)
    802             {
    803                 RTListNodeRemove(&pProv->ListEntry);
    804                 supdrvVtgFreeProvider(pProv);
    805             }
    806             else if (!(i & 0xf))
    807                 SUPR0Printf("supdrvVtgTerm: Waiting on busy provider '%s' / %p (rc=%d)\n", pProv->szName, pProv->idDtProv, rc);
    808             else
    809                 LOG_DTRACE(("supdrvVtgTerm: Failed to unregister provider '%s' / %p - rc=%d\n", pProv->szName, pProv->idDtProv, rc));
    810         }
    811 
    812         fEmpty = RTListIsEmpty(&pDevExt->DtProviderZombieList);
    813         RTSemFastMutexRelease(pDevExt->mtxDTrace);
    814         if (fEmpty)
    815             break;
    816 
    817         /* Delay...*/
    818         RTThreadSleep(1000);
    819     }
    820 
    821     RTSemFastMutexDestroy(pDevExt->mtxDTrace);
    822     pDevExt->mtxDTrace = NIL_RTSEMFASTMUTEX;
    823     LOG_DTRACE(("supdrvVtgTerm: Done\n"));
    824 }
    825 
    826 
    827 /**
    828  * @callback_method_impl{dtrace_pops_t,dtps_provide}
    829  */
    830 static void     supdrvDTracePOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc)
    831 {
    832     PSUPDRVDTPROVIDER   pProv      = (PSUPDRVDTPROVIDER)pvProv;
    833     uint16_t            idxProv;
    834     PVTGPROBELOC        pProbeLoc;
    835     PVTGPROBELOC        pProbeLocEnd;
    836     char               *pszFnNmBuf;
    837     size_t const        cbFnNmBuf = _4K + _1K;
    838 
    839     if (pDtProbeDesc)
    840         return;  /* We don't generate probes, so never mind these requests. */
    841 
    842     if (pProv->fZombie)
    843         return;
    844 
    845     if (pProv->cProvidedProbes >= pProv->pDesc->cProbes)
    846         return;
    847 
    848      /* Need a buffer for extracting the function names and mangling them in
    849         case of collision. */
    850      pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf);
    851      if (!pszFnNmBuf)
    852          return;
    853 
    854      /*
    855       * Itereate the probe location list and register all probes related to
    856       * this provider.
    857       */
    858      idxProv      = (uint16_t)(&pProv->pHdr->paProviders[0] - pProv->pDesc);
    859      pProbeLoc    = pProv->pHdr->paProbLocs;
    860      pProbeLocEnd = pProv->pHdr->paProbLocsEnd;
    861      while ((uintptr_t)pProbeLoc < (uintptr_t)pProbeLocEnd)
    862      {
    863          PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
    864          if (   pProbeDesc->idxProvider == idxProv
    865              && pProbeLoc->idProbe      == UINT32_MAX)
    866          {
    867              /* The function name normally needs to be stripped since we're
    868                 using C++ compilers for most of the code.  ASSUMES nobody are
    869                 brave/stupid enough to use function pointer returns without
    870                 typedef'ing properly them. */
    871              const char *pszPrbName = supdrvVtgGetString(pProv->pHdr, pProbeDesc->offName);
    872              const char *pszFunc    = pProbeLoc->pszFunction;
    873              const char *psz        = strchr(pProbeLoc->pszFunction, '(');
    874              size_t      cch;
    875              if (psz)
    876              {
    877                  /* skip blanks preceeding the parameter parenthesis. */
    878                  while (   (uintptr_t)psz > (uintptr_t)pProbeLoc->pszFunction
    879                         && RT_C_IS_BLANK(psz[-1]))
    880                      psz--;
    881 
    882                  /* Find the start of the function name. */
    883                  pszFunc = psz - 1;
    884                  while ((uintptr_t)pszFunc > (uintptr_t)pProbeLoc->pszFunction)
    885                  {
    886                      char ch = pszFunc[-1];
    887                      if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':')
    888                          break;
    889                      pszFunc--;
    890                  }
    891                  cch = psz - pszFunc;
    892              }
    893              else
    894                  cch = strlen(pszFunc);
    895              RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch);
    896 
    897              /* Look up the probe, if we have one in the same function, mangle
    898                 the function name a little to avoid having to deal with having
    899                 multiple location entries with the same probe ID. (lazy bird) */
    900              Assert(pProbeLoc->idProbe == UINT32_MAX);
    901              if (dtrace_probe_lookup(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
    902              {
    903                  RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u",  pProbeLoc->uLine);
    904                  if (dtrace_probe_lookup(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
    905                  {
    906                      unsigned iOrd = 2;
    907                      while (iOrd < 128)
    908                      {
    909                          RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u",  pProbeLoc->uLine, iOrd);
    910                          if (dtrace_probe_lookup(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE)
    911                              break;
    912                          iOrd++;
    913                      }
    914                      if (iOrd >= 128)
    915                      {
    916                          LogRel(("VBoxDrv: More than 128 duplicate probe location instances in file %s at line %u, function %s [%s], probe %s\n",
    917                                  pProbeLoc->pszFile, pProbeLoc->uLine, pProbeLoc->pszFunction, pszFnNmBuf, pszPrbName));
    918                          continue;
    919                      }
    920                  }
    921              }
    922 
    923              /* Create the probe. */
    924              AssertCompile(sizeof(pProbeLoc->idProbe) == sizeof(dtrace_id_t));
    925              pProbeLoc->idProbe = dtrace_probe_create(pProv->idDtProv, pProv->pszModName, pszFnNmBuf, pszPrbName,
    926                                                       0 /*aframes*/, pProbeLoc);
    927              pProv->cProvidedProbes++;
    928          }
    929 
    930          pProbeLoc++;
    931      }
    932 
    933      RTMemFree(pszFnNmBuf);
    934 }
    935 
    936 
    937 /**
    938  * @callback_method_impl{dtrace_pops_t,dtps_enable}
    939  */
    940 static int      supdrvDTracePOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
    941 {
    942     PSUPDRVDTPROVIDER   pProv      = (PSUPDRVDTPROVIDER)pvProv;
    943     if (!pProv->fZombie)
    944     {
    945         PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
    946         PVTGDESCPROBE   pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
    947 
    948         if (!pProbeLoc->fEnabled)
    949         {
    950             pProbeLoc->fEnabled = 1;
    951             if (ASMAtomicIncU32(&pProbeDesc->u32User) == 1)
    952                 pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1;
    953         }
    954     }
    955 
    956     return 0;
    957 }
    958 
    959 
    960 /**
    961  * @callback_method_impl{dtrace_pops_t,dtps_disable}
    962  */
    963 static void     supdrvDTracePOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
    964 {
    965     PSUPDRVDTPROVIDER   pProv      = (PSUPDRVDTPROVIDER)pvProv;
    966     if (!pProv->fZombie)
    967     {
    968         PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
    969         PVTGDESCPROBE   pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
    970 
    971         if (pProbeLoc->fEnabled)
    972         {
    973             pProbeLoc->fEnabled = 0;
    974             if (ASMAtomicDecU32(&pProbeDesc->u32User) == 0)
    975                 pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1;
    976         }
    977     }
    978 }
    979 
    980 
    981 /**
    982  * @callback_method_impl{dtrace_pops_t,dtps_getargdesc}
    983  */
    984 static void     supdrvDTracePOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
    985                                             dtrace_argdesc_t *pArgDesc)
    986 {
    987     PSUPDRVDTPROVIDER   pProv      = (PSUPDRVDTPROVIDER)pvProv;
    988     unsigned            uArg       = pArgDesc->dtargd_ndx;
    989 
    990     if (!pProv->fZombie)
    991     {
    992         PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
    993         PVTGDESCPROBE   pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
    994         PVTGDESCARGLIST pArgList   = (PVTGDESCARGLIST)((uintptr_t)pProv->pHdr->paArgLists + pProbeDesc->offArgList);
    995 
    996         Assert(pProbeDesc->offArgList < pProv->pHdr->cbArgLists);
    997         if (pArgList->cArgs > uArg)
    998         {
    999             const char *pszType = supdrvVtgGetString(pProv->pHdr, pArgList->aArgs[uArg].offType);
    1000             size_t      cchType = strlen(pszType);
    1001             if (cchType < sizeof(pArgDesc->dtargd_native))
    1002             {
    1003                 memcpy(pArgDesc->dtargd_native, pszType, cchType + 1);
    1004                 /** @todo mapping */
    1005                 return;
    1006             }
    1007         }
    1008     }
    1009 
    1010     pArgDesc->dtargd_ndx = DTRACE_ARGNONE;
    1011 }
    1012 
    1013 
    1014 #ifdef RT_OS_SOLARIS
    1015 
    1016 # ifdef __cplusplus
    1017 extern "C"
    1018 #endif
    1019 uint64_t dtrace_getarg(int iArg, int cFrames);
    1020 
    1021 /**
    1022  * @callback_method_impl{dtrace_pops_t,dtps_getargval}
    1023  */
    1024 static uint64_t supdrvDTracePOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
    1025                                            int iArg, int cFrames)
    1026 {
    1027     /* dtrace_getarg on AMD64 has a different opinion about how to use the
    1028        cFrames argument than dtrace_caller() and/or dtrace_getpcstack(), at
    1029        least when the probe is fired by dtrace_probe() the way we do.
    1030      
    1031        Setting aframes to 1 when calling dtrace_probe_create gives me the right
    1032        arguments, but the wrong 'caller'.  Since I cannot do anything about
    1033        'caller', the only solution is this hack.
    1034      
    1035        Not sure why the Solaris guys hasn't seen this issue before, but maybe
    1036        there isn't anyone using the default argument getter path for ring-0
    1037        dtrace_probe() calls, SDT surely isn't.
    1038      
    1039        WARNING! This code is subject to dtrace_getarg interface unstability! */
    1040     /** @todo File a solaris bug on dtrace_probe() + dtrace_getarg(). */
    1041     return dtrace_getarg(iArg, cFrames + 1);
    1042 }
    1043 
    1044 #endif /* RT_OS_SOLARIS */
    1045 
    1046 
    1047 /**
    1048  * @callback_method_impl{dtrace_pops_t,dtps_destroy}
    1049  */
    1050 static void    supdrvDTracePOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
    1051 {
    1052     PSUPDRVDTPROVIDER   pProv      = (PSUPDRVDTPROVIDER)pvProv;
    1053     if (!pProv->fZombie)
    1054     {
    1055         PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
    1056         Assert(!pProbeLoc->fEnabled);
    1057         Assert(pProbeLoc->idProbe == idProbe); NOREF(idProbe);
    1058         pProbeLoc->idProbe = UINT32_MAX;
    1059     }
    1060     pProv->cProvidedProbes--;
    1061 }
    1062 
     912void VBOXCALL supdrvTracerTerm(PSUPDRVDEVEXT pDevExt)
     913{
     914    LOG_TRACER(("supdrvTracerTerm\n"));
     915
     916    supdrvTracerRemoveAllProviders(pDevExt);
     917
     918    RTSemFastMutexDestroy(pDevExt->mtxTracer);
     919    pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
     920    LOG_TRACER(("supdrvTracerTerm: Done\n"));
     921}
     922
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r40741 r40756  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    466466                    if (RT_SUCCESS(rc))
    467467                    {
    468 #ifdef VBOX_WITH_DTRACE_R0DRV
     468#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     469                        rc = supdrvTracerInit(pDevExt);
     470#elif defined(VBOX_WITH_DTRACE_R0DRV)
    469471                        rc = supdrvVtgInit(pDevExt, &g_aFunctions[10]);
    470472                        if (RT_SUCCESS(rc))
     
    531533                        }
    532534
    533 #ifdef VBOX_WITH_DTRACE_R0DRV
     535#if defined(VBOX_WITH_SUPDRV_GENERIC_TRACER) || defined(VBOX_WITH_DTRACE_R0DRV)
    534536                        supdrvGipDestroy(pDevExt);
    535537#endif
     
    626628    supdrvGipDestroy(pDevExt);
    627629
    628 #ifdef VBOX_WITH_DTRACE_R0DRV
     630#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     631    supdrvTracerTerm(pDevExt);
     632#elif defined(VBOX_WITH_DTRACE_R0DRV)
    629633    supdrvVtgTerm(pDevExt);
    630634#endif
     
    816820    }
    817821    Log2(("release objects - done\n"));
     822
     823#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     824    /*
     825     * Do tracer cleanups related to this session.
     826     */
     827    Log2(("release tracer stuff - start\n"));
     828    supdrvTracerCleanupSession(pDevExt, pSession);
     829    Log2(("release tracer stuff - end\n"));
     830#endif
    818831
    819832    /*
     
    36673680
    36683681
    3669 #if !defined(VBOX_WITH_DTRACE_R0DRV) || defined(RT_OS_SOLARIS)
     3682#if (!defined(VBOX_WITH_SUPDRV_GENERIC_TRACER) && !defined(VBOX_WITH_DTRACE_R0DRV)) \
     3683  || defined(RT_OS_SOLARIS)
    36703684/**
    36713685 * Stub function.
     
    36783692#endif
    36793693
    3680 #ifndef VBOX_WITH_DTRACE_R0DRV
     3694#if !defined(VBOX_WITH_SUPDRV_GENERIC_TRACER) && !defined(VBOX_WITH_DTRACE_R0DRV)
    36813695/**
    36823696 * Stub function.
     
    41514165    if (RT_FAILURE(rc))
    41524166    {
    4153 #ifdef VBOX_WITH_DTRACE_R0DRV
    41544167        /* Inform the tracing component in case ModuleInit registered TPs. */
     4168#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     4169        supdrvTracerModuleUnloading(pDevExt, pImage);
     4170#elif defined(VBOX_WITH_DTRACE_R0DRV)
    41554171        supdrvVtgModuleUnloading(pDevExt, pImage);
    41564172#endif
     
    46004616    }
    46014617
    4602 #ifdef VBOX_WITH_DTRACE_R0DRV
    46034618    /* Inform the tracing component. */
     4619#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     4620    supdrvTracerModuleUnloading(pDevExt, pImage);
     4621#elif defined(VBOX_WITH_DTRACE_R0DRV)
    46044622    supdrvVtgModuleUnloading(pDevExt, pImage);
    46054623#endif
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r40675 r40756  
    496496
    497497    /** @name These members for detecting whether an API caller is in ModuleInit.
    498      * Certain APIs are only permitted from ModuleInit, like for instance tracepoint 
    499      * registration. 
     498     * Certain APIs are only permitted from ModuleInit, like for instance tracepoint
     499     * registration.
    500500     * @{ */
    501501    /** The image currently executing its ModuleInit. */
     
    537537    PSUPDRVFACTORYREG               pComponentFactoryHead;
    538538
    539 #ifdef VBOX_WITH_DTRACE_R0DRV
    540     /** Lock protecting DtProviderList. */
    541     RTSEMFASTMUTEX                  mtxDTrace;
     539#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     540    /** Lock protecting The tracer members. */
     541    RTSEMFASTMUTEX                  mtxTracer;
     542    /** List of tracer providers (SUPDRVTPPROVIDER). */
     543    RTLISTANCHOR                    TracerProviderList;
     544    /** List of zombie tracer providers (SUPDRVTPPROVIDER). */
     545    RTLISTANCHOR                    TracerProviderZombieList;
     546    /** Pointer to the tracer registration record. */
     547    PCSUPDRVTRACERREG               pTracerOps;
     548    /** The ring-0 session of a native tracer provider. */
     549    PSUPDRVSESSION                  pTracerSession;
     550    /** The image containing the tracer. */
     551    PSUPDRVLDRIMAGE                 pTracerImage;
     552    /** The tracer helpers. */
     553    SUPDRVTRACERHLP                 TracerHlp;
     554    /** Set if the tracer is being unloaded. */
     555    bool                            fTracerUnloading;
     556
     557#elif defined(VBOX_WITH_DTRACE_R0DRV)
    542558    /** List of DTrace providers (SUPDRVDTPROVIDER). */
    543559    RTLISTANCHOR                    DtProviderList;
     
    641657#endif
    642658
     659#ifdef VBOX_WITH_SUPDRV_GENERIC_TRACER
     660int  VBOXCALL   supdrvTracerInit(PSUPDRVDEVEXT pDevExt);
     661void VBOXCALL   supdrvTracerTerm(PSUPDRVDEVEXT pDevExt);
     662void VBOXCALL   supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
     663void VBOXCALL   supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
     664#endif
     665
    643666
    644667RT_C_DECLS_END
Note: See TracChangeset for help on using the changeset viewer.

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