VirtualBox

Ignore:
Timestamp:
Jan 2, 2015 12:33:32 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
97446
Message:

VBoxDTrace: Implemented all the fake solaris stuff. (r46)

Location:
trunk/src/VBox/ExtPacks/VBoxDTrace
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ExtPacks/VBoxDTrace/VBoxDTraceR0/VBoxDTraceR0.cpp

    r53668 r53669  
    4242#include <iprt/mem.h>
    4343#include <iprt/mp.h>
     44#include <iprt/process.h>
    4445#include <iprt/semaphore.h>
    4546#include <iprt/spinlock.h>
     
    108109    /** Credentials allocated by VBoxDtGetCurrentCreds. */
    109110    struct VBoxDtCred      *pCred;
     111    /** Thread structure currently being held by this thread. */
     112    struct VBoxDtThread    *pThread;
    110113    /** Pointer to this structure.
    111114     * This is the final bit of integrity checking. */
     
    145148        if (pStackData->pCred) \
    146149            crfree(pStackData->pCred); \
     150        if (pStackData->pThread) \
     151            VBoxDtReleaseThread(pStackData->pThread); \
    147152    } while (0)
    148153
     
    677682        RTMemFree(pCred);
    678683}
     684
     685/** Spinlock protecting the thread structures. */
     686static RTSPINLOCK           g_hThreadSpinlock = NIL_RTSPINLOCK;
     687/** List of threads by usage age. */
     688static RTLISTANCHOR         g_ThreadAgeList;
     689/** Hash table for looking up thread structures.  */
     690static struct VBoxDtThread *g_apThreadsHash[16384];
     691/** Fake kthread_t structures.
     692 * The size of this array is making horrible ASSUMPTIONS about the number of
     693 * thread in the system that will be subjected to DTracing. */
     694static struct VBoxDtThread  g_aThreads[8192];
     695
     696
     697static int vboxDtInitThreadDb(void)
     698{
     699    int rc = RTSpinlockCreate(&g_hThreadSpinlock);
     700    if (RT_FAILURE(rc))
     701        return rc;
     702
     703    RTListInit(&g_ThreadAgeList);
     704    for (uint32_t i = 0; i < RT_ELEMENTS(g_aThreads); i++)
     705    {
     706        g_aThreads[i].hNative = NIL_RTNATIVETHREAD;
     707        g_aThreads[i].uPid    = NIL_RTPROCESS;
     708        RTListPrepend(&g_ThreadAgeList, &g_aThreads[i].AgeEntry);
     709    }
     710
     711    return VINF_SUCCESS;
     712}
     713
     714
     715static void vboxDtTermThreadDb(void)
     716{
     717    RTSpinlockDestroy(g_hThreadSpinlock);
     718    g_hThreadSpinlock = NIL_RTSPINLOCK;
     719    RTListInit(&g_ThreadAgeList);
     720}
     721
     722
     723/* curthread implementation, providing a fake kthread_t. */
     724struct VBoxDtThread *VBoxDtGetCurrentThread(void)
     725{
     726    /*
     727     * Once we've retrieved a thread, we hold on to it until the thread exits
     728     * the VBoxDTrace module.
     729     */
     730    PVBDTSTACKDATA  pData       = vboxDtGetStackData();
     731    if (pData->pThread)
     732    {
     733        AssertPtr(pData->pThread);
     734        Assert(pData->pThread->hNative   == RTThreadNativeSelf());
     735        Assert(pData->pThread->uPid      == RTProcSelf());
     736        Assert(RTListIsEmpty(&pData->pThread->AgeEntry));
     737        return pData->pThread;
     738    }
     739
     740    /*
     741     * Lookup the thread in the hash table.
     742     */
     743    RTNATIVETHREAD  hNativeSelf = RTThreadNativeSelf();
     744    RTPROCESS       uPid        = RTProcSelf();
     745    uintptr_t       iHash       = (hNativeSelf * 2654435761) % RT_ELEMENTS(g_apThreadsHash);
     746    RTSPINLOCKTMP   Tmp         = RTSPINLOCKTMP_INITIALIZER;
     747
     748    RTSpinlockAcquireNoInts(g_hThreadSpinlock, &Tmp);
     749
     750    struct VBoxDtThread *pThread = g_apThreadsHash[iHash];
     751    while (pThread)
     752    {
     753        if (pThread->hNative == hNativeSelf)
     754        {
     755            if (pThread->uPid != uPid)
     756            {
     757                /* Re-initialize the reused thread. */
     758                pThread->uPid           = uPid;
     759                pThread->t_dtrace_vtime = 0;
     760                pThread->t_dtrace_start = 0;
     761                pThread->t_dtrace_stop  = 0;
     762                pThread->t_dtrace_scrpc = 0;
     763                pThread->t_dtrace_astpc = 0;
     764                pThread->t_predcache    = 0;
     765            }
     766
     767            /* Hold the thread in the on-stack data, making sure it does not
     768               get reused till the thread leaves VBoxDTrace. */
     769            RTListNodeRemove(&pThread->AgeEntry);
     770            pData->pThread = pThread;
     771
     772            RTSpinlockReleaseNoInts(g_hThreadSpinlock, &Tmp);
     773            return pThread;
     774        }
     775
     776        pThread = pThread->pNext;
     777    }
     778
     779    /*
     780     * Unknown thread.  Allocate a new entry, recycling unused or old ones.
     781     */
     782    pThread = RTListGetLast(&g_ThreadAgeList, struct VBoxDtThread, AgeEntry);
     783    AssertFatal(pThread);
     784    RTListNodeRemove(&pThread->AgeEntry);
     785    if (pThread->hNative != NIL_RTNATIVETHREAD)
     786    {
     787        uintptr_t   iHash2 = (pThread->hNative * 2654435761) % RT_ELEMENTS(g_apThreadsHash);
     788        if (g_apThreadsHash[iHash2] == pThread)
     789            g_apThreadsHash[iHash2] = pThread->pNext;
     790        else
     791        {
     792            for (struct VBoxDtThread *pPrev = g_apThreadsHash[iHash2]; ; pPrev = pPrev->pNext)
     793            {
     794                AssertPtr(pPrev);
     795                if (pPrev->pNext == pThread)
     796                {
     797                    pPrev->pNext = pThread->pNext;
     798                    break;
     799                }
     800            }
     801        }
     802    }
     803
     804    /*
     805     * Initialize the data.
     806     */
     807    pThread->t_dtrace_vtime = 0;
     808    pThread->t_dtrace_start = 0;
     809    pThread->t_dtrace_stop  = 0;
     810    pThread->t_dtrace_scrpc = 0;
     811    pThread->t_dtrace_astpc = 0;
     812    pThread->t_predcache    = 0;
     813    pThread->hNative        = hNativeSelf;
     814    pThread->uPid           = uPid;
     815
     816    /*
     817     * Add it to the hash as well as the on-stack data.
     818     */
     819    pThread->pNext = g_apThreadsHash[iHash];
     820    g_apThreadsHash[iHash] = pThread->pNext;
     821
     822    pData->pThread = pThread;
     823
     824    RTSpinlockReleaseNoInts(g_hThreadSpinlock, &Tmp);
     825    return pThread;
     826}
     827
     828
     829/**
     830 * Called by the stack data destructor.
     831 *
     832 * @param   pThread         The thread to release.
     833 *
     834 */
     835static void VBoxDtReleaseThread(struct VBoxDtThread *pThread)
     836{
     837    RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
     838    RTSpinlockAcquireNoInts(g_hThreadSpinlock, &Tmp);
     839
     840    RTListAppend(&g_ThreadAgeList, &pThread->AgeEntry);
     841
     842    RTSpinlockReleaseNoInts(g_hThreadSpinlock, &Tmp);
     843}
     844
     845
    679846
    680847
     
    10621229    RTMemFreeEx(pvMem, pThis->cbBuf);
    10631230}
    1064 
    1065 
    1066 #if 0
    1067 VBoxDtGetKernelBase
    1068 VBoxDtGetCurrentThread
    1069 #endif
    1070 
    10711231
    10721232
  • trunk/src/VBox/ExtPacks/VBoxDTrace/include/VBoxDTraceTypes.h

    r53668 r53669  
    3535#include <iprt/stdarg.h>
    3636#include <iprt/param.h>
     37#ifdef IN_RING0
     38# include <iprt/list.h>
     39#endif
    3740#ifdef IN_RING3
    3841# include <sys/types.h>
     
    218221typedef struct VBoxDtThread
    219222{
     223    /** The next thread with the same hash table entry.
     224     * Or the next free thread.  */
     225    struct VBoxDtThread    *pNext;
     226    /** Age list node. */
     227    RTLISTNODE              AgeEntry;
     228    /** The native thread handle. */
     229    RTNATIVETHREAD          hNative;
     230    /** The process ID. */
     231    RTPROCESS               uPid;
     232
     233    uint32_t                t_predcache;
     234    uintptr_t               t_dtrace_scrpc;
     235    uintptr_t               t_dtrace_astpc;
    220236    hrtime_t                t_dtrace_vtime;
    221237    hrtime_t                t_dtrace_start;
    222238    uint8_t                 t_dtrace_stop;
    223     uintptr_t               t_dtrace_scrpc;
    224     uintptr_t               t_dtrace_astpc;
    225     uint32_t                t_predcache;
    226     struct VBoxDtProcess   *t_proc;
    227239} kthread_t;
    228240struct VBoxDtThread *VBoxDtGetCurrentThread(void);
  • trunk/src/VBox/ExtPacks/VBoxDTrace/onnv/uts/common/dtrace/dtrace.c

    r53668 r53669  
    9797# include <iprt/assert.h>
    9898# include <iprt/cpuset.h>
     99# include <iprt/mem.h>
    99100# include <iprt/mp.h>
    100101# include <iprt/string.h>
     
    138139# define NULL (0)
    139140#endif /* VBOX */
     141
     142/** Check if the given address is a valid kernel address.
     143 * The value can be uintptr_t or uint64_t.  */
     144#ifndef VBOX
     145# define VBDT_IS_VALID_KRNL_ADDR(a_uAddr)   ((a_uAddr) >= KERNELBASE)
     146#else
     147# define VBDT_IS_VALID_KRNL_ADDR(a_uAddr)   \
     148    (   (sizeof(a_uAddr) == sizeof(uintptr_t) || (uintptr_t)(a_uAddr) == (a_uAddr)) \
     149     && RTR0MemKernelIsValidAddr((void *)(uintptr_t)(a_uAddr)) )
     150#endif
     151
    140152
    141153/*
     
    232244static kmem_cache_t     *dtrace_state_cache;    /* cache for dynamic state */
    233245static uint64_t         dtrace_vtime_references; /* number of vtimestamp refs */
     246#ifndef VBOX
    234247static kthread_t        *dtrace_panicked;       /* panicking thread */
     248#endif
    235249static dtrace_ecb_t     *dtrace_ecb_create_cache; /* cached created ECB */
    236250static dtrace_genid_t   dtrace_probegen;        /* current probe generation */
     
    93679381
    93689382        ASSERT(!DTRACEACT_ISPRINTFLIKE(kind) || (arg != NULL &&
    9369             arg >= KERNELBASE) || (arg == NULL && kind == DTRACEACT_PRINTA));
     9383            VBDT_IS_VALID_KRNL_ADDR(arg)) || (arg == NULL && kind == DTRACEACT_PRINTA));
    93709384
    93719385        act = kmem_zalloc(sizeof (dtrace_actdesc_t), KM_SLEEP);
     
    94039417                char *str = (char *)(uintptr_t)act->dtad_arg;
    94049418
    9405                 ASSERT((str != NULL && (uintptr_t)str >= KERNELBASE) ||
     9419                ASSERT((str != NULL && VBDT_IS_VALID_KRNL_ADDR((uintptr_t)str)) ||
    94069420                    (str == NULL && act->dtad_kind == DTRACEACT_PRINTA));
    94079421
     
    98789892                        } else {
    98799893                                ASSERT(arg != NULL);
    9880                                 ASSERT(arg > KERNELBASE);
     9894                                ASSERT(VBDT_IS_VALID_KRNL_ADDR(arg));
    98819895                                format = dtrace_format_add(state,
    98829896                                    (char *)(uintptr_t)arg);
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