Changeset 53669 in vbox for trunk/src/VBox/ExtPacks/VBoxDTrace
- Timestamp:
- Jan 2, 2015 12:33:32 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 97446
- Location:
- trunk/src/VBox/ExtPacks/VBoxDTrace
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ExtPacks/VBoxDTrace/VBoxDTraceR0/VBoxDTraceR0.cpp
r53668 r53669 42 42 #include <iprt/mem.h> 43 43 #include <iprt/mp.h> 44 #include <iprt/process.h> 44 45 #include <iprt/semaphore.h> 45 46 #include <iprt/spinlock.h> … … 108 109 /** Credentials allocated by VBoxDtGetCurrentCreds. */ 109 110 struct VBoxDtCred *pCred; 111 /** Thread structure currently being held by this thread. */ 112 struct VBoxDtThread *pThread; 110 113 /** Pointer to this structure. 111 114 * This is the final bit of integrity checking. */ … … 145 148 if (pStackData->pCred) \ 146 149 crfree(pStackData->pCred); \ 150 if (pStackData->pThread) \ 151 VBoxDtReleaseThread(pStackData->pThread); \ 147 152 } while (0) 148 153 … … 677 682 RTMemFree(pCred); 678 683 } 684 685 /** Spinlock protecting the thread structures. */ 686 static RTSPINLOCK g_hThreadSpinlock = NIL_RTSPINLOCK; 687 /** List of threads by usage age. */ 688 static RTLISTANCHOR g_ThreadAgeList; 689 /** Hash table for looking up thread structures. */ 690 static 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. */ 694 static struct VBoxDtThread g_aThreads[8192]; 695 696 697 static 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 715 static 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. */ 724 struct 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 */ 835 static 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 679 846 680 847 … … 1062 1229 RTMemFreeEx(pvMem, pThis->cbBuf); 1063 1230 } 1064 1065 1066 #if 01067 VBoxDtGetKernelBase1068 VBoxDtGetCurrentThread1069 #endif1070 1071 1231 1072 1232 -
trunk/src/VBox/ExtPacks/VBoxDTrace/include/VBoxDTraceTypes.h
r53668 r53669 35 35 #include <iprt/stdarg.h> 36 36 #include <iprt/param.h> 37 #ifdef IN_RING0 38 # include <iprt/list.h> 39 #endif 37 40 #ifdef IN_RING3 38 41 # include <sys/types.h> … … 218 221 typedef struct VBoxDtThread 219 222 { 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; 220 236 hrtime_t t_dtrace_vtime; 221 237 hrtime_t t_dtrace_start; 222 238 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;227 239 } kthread_t; 228 240 struct VBoxDtThread *VBoxDtGetCurrentThread(void); -
trunk/src/VBox/ExtPacks/VBoxDTrace/onnv/uts/common/dtrace/dtrace.c
r53668 r53669 97 97 # include <iprt/assert.h> 98 98 # include <iprt/cpuset.h> 99 # include <iprt/mem.h> 99 100 # include <iprt/mp.h> 100 101 # include <iprt/string.h> … … 138 139 # define NULL (0) 139 140 #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 140 152 141 153 /* … … 232 244 static kmem_cache_t *dtrace_state_cache; /* cache for dynamic state */ 233 245 static uint64_t dtrace_vtime_references; /* number of vtimestamp refs */ 246 #ifndef VBOX 234 247 static kthread_t *dtrace_panicked; /* panicking thread */ 248 #endif 235 249 static dtrace_ecb_t *dtrace_ecb_create_cache; /* cached created ECB */ 236 250 static dtrace_genid_t dtrace_probegen; /* current probe generation */ … … 9367 9381 9368 9382 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)); 9370 9384 9371 9385 act = kmem_zalloc(sizeof (dtrace_actdesc_t), KM_SLEEP); … … 9403 9417 char *str = (char *)(uintptr_t)act->dtad_arg; 9404 9418 9405 ASSERT((str != NULL && (uintptr_t)str >= KERNELBASE) ||9419 ASSERT((str != NULL && VBDT_IS_VALID_KRNL_ADDR((uintptr_t)str)) || 9406 9420 (str == NULL && act->dtad_kind == DTRACEACT_PRINTA)); 9407 9421 … … 9878 9892 } else { 9879 9893 ASSERT(arg != NULL); 9880 ASSERT( arg > KERNELBASE);9894 ASSERT(VBDT_IS_VALID_KRNL_ADDR(arg)); 9881 9895 format = dtrace_format_add(state, 9882 9896 (char *)(uintptr_t)arg);
Note:
See TracChangeset
for help on using the changeset viewer.