Changeset 46443 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jun 7, 2013 4:18:29 PM (12 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/STAM.cpp
r46439 r46443 59 59 #include <iprt/assert.h> 60 60 #include <iprt/asm.h> 61 #include <iprt/ alloc.h>61 #include <iprt/mem.h> 62 62 #include <iprt/stream.h> 63 63 #include <iprt/string.h> … … 133 133 * Internal Functions * 134 134 *******************************************************************************/ 135 #ifdef STAM_WITH_LOOKUP_TREE 136 static void stamR3LookupDestroyTree(PSTAMLOOKUP pRoot); 137 #endif 135 138 static int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint, 136 139 STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc); … … 272 275 273 276 /* 274 * Initialize the read/write lock .277 * Initialize the read/write lock and list. 275 278 */ 276 279 int rc = RTSemRWCreate(&pUVM->stam.s.RWSem); 277 280 AssertRCReturn(rc, rc); 281 282 RTListInit(&pUVM->stam.s.List); 283 284 #ifdef STAM_WITH_LOOKUP_TREE 285 /* 286 * Initialize the root node. 287 */ 288 PSTAMLOOKUP pRoot = (PSTAMLOOKUP)RTMemAlloc(sizeof(STAMLOOKUP)); 289 if (!pRoot) 290 { 291 RTSemRWDestroy(pUVM->stam.s.RWSem); 292 pUVM->stam.s.RWSem = NIL_RTSEMRW; 293 return VERR_NO_MEMORY; 294 } 295 pRoot->pParent = NULL; 296 pRoot->papChildren = NULL; 297 pRoot->pDesc = NULL; 298 pRoot->cDescsInTree = 0; 299 pRoot->cChildren = 0; 300 pRoot->iParent = UINT16_MAX; 301 pRoot->off = 0; 302 pRoot->cch = 0; 303 pRoot->szName[0] = '\0'; 304 305 pUVM->stam.s.pRoot = pRoot; 306 #endif 307 278 308 279 309 /* … … 309 339 * Free used memory and the RWLock. 310 340 */ 311 PSTAMDESC pCur = pUVM->stam.s.pHead; 312 while (pCur) 313 { 314 void *pvFree = pCur; 315 pCur = pCur->pNext; 316 RTMemFree(pvFree); 317 } 318 pUVM->stam.s.pHead = NULL; 341 PSTAMDESC pCur, pNext; 342 RTListForEachSafe(&pUVM->stam.s.List, pCur, pNext, STAMDESC, ListEntry) 343 { 344 #ifdef STAM_WITH_LOOKUP_TREE 345 pCur->pLookup->pDesc = NULL; 346 #endif 347 RTMemFree(pCur); 348 } 349 350 #ifdef STAM_WITH_LOOKUP_TREE 351 stamR3LookupDestroyTree(pUVM->stam.s.pRoot); 352 pUVM->stam.s.pRoot = NULL; 353 #endif 319 354 320 355 Assert(pUVM->stam.s.RWSem != NIL_RTSEMRW); … … 577 612 } 578 613 #endif /* VBOX_STRICT */ 614 615 616 #ifdef STAM_WITH_LOOKUP_TREE 617 618 /** 619 * Compares a lookup node with a name. 620 * 621 * @returns like strcmp and memcmp. 622 * @param pNode The lookup node. 623 * @param pchName The name, not necessarily terminated. 624 * @param cchName The length of the name. 625 */ 626 DECL_FORCE_INLINE(int) stamR3LookupCmp(PSTAMLOOKUP pNode, const char *pchName, uint32_t cchName) 627 { 628 uint32_t cchComp = RT_MIN(pNode->cch, cchName); 629 int iDiff = memcmp(pNode->szName, pchName, cchComp); 630 if (!iDiff && pNode->cch != cchName) 631 iDiff = pNode->cch > cchName ? 2 : -2; 632 return iDiff; 633 } 634 635 636 /** 637 * Creates a new lookup child node. 638 * 639 * @returns Pointer to the newly created lookup node. 640 * @param pParent The parent node. 641 * @param pchName The name (not necessarily terminated). 642 * @param cchName The length of the name. 643 * @param offName The offset of the node in a path. 644 * @param iChild Child index of a node that's before the one 645 * we're inserting (returned by 646 * stamR3LookupFindChild). 647 */ 648 static PSTAMLOOKUP stamR3LookupNewChild(PSTAMLOOKUP pParent, const char *pchName, uint32_t cchName, uint32_t offName, 649 uint32_t iChild) 650 { 651 Assert(cchName <= UINT8_MAX); 652 Assert(offName <= UINT8_MAX); 653 Assert(iChild < UINT16_MAX); 654 655 /* 656 * Allocate a new entry. 657 */ 658 PSTAMLOOKUP pNew = (PSTAMLOOKUP)RTMemAlloc(RT_OFFSETOF(STAMLOOKUP, szName[cchName + 1])); 659 if (!pNew) 660 return NULL; 661 pNew->pParent = pParent; 662 pNew->papChildren = NULL; 663 pNew->pDesc = NULL; 664 pNew->cDescsInTree = 0; 665 pNew->cChildren = 0; 666 pNew->cch = (uint16_t)cchName; 667 pNew->off = (uint16_t)offName; 668 memcpy(pNew->szName, pchName, cchName); 669 pNew->szName[cchName] = '\0'; 670 671 /* 672 * Reallocate the array? 673 */ 674 if (RT_IS_POWER_OF_TWO(pParent->cChildren)) 675 { 676 uint32_t cNew = pParent->cChildren ? (uint32_t)pParent->cChildren * 2 : 8; 677 AssertReturnStmt(cNew <= 0x8000, RTMemFree(pNew), NULL); 678 void *pvNew = RTMemRealloc(pParent->papChildren, cNew * sizeof(pParent->papChildren[0])); 679 if (!pvNew) 680 { 681 RTMemFree(pNew); 682 return NULL; 683 } 684 pParent->papChildren = (PSTAMLOOKUP *)pvNew; 685 } 686 687 /* 688 * Find the exact insertion point using iChild as a very good clue from 689 * the find function. 690 */ 691 if (!pParent->cChildren) 692 iChild = 0; 693 else 694 { 695 if (iChild >= pParent->cChildren) 696 iChild = pParent->cChildren - 1; 697 while ( iChild < pParent->cChildren 698 && stamR3LookupCmp(pParent->papChildren[iChild], pchName, cchName) < 0) 699 iChild++; 700 } 701 702 /* 703 * Insert it. 704 */ 705 if (iChild < pParent->cChildren) 706 { 707 /* Do shift. */ 708 uint32_t i = pParent->cChildren; 709 while (i > iChild) 710 { 711 PSTAMLOOKUP pNode = pParent->papChildren[i - 1]; 712 pParent->papChildren[i] = pNode; 713 pNode->iParent = i; 714 i--; 715 } 716 } 717 718 pNew->iParent = iChild; 719 pParent->papChildren[iChild] = pNew; 720 pParent->cChildren++; 721 722 return pNew; 723 } 724 725 726 /** 727 * Looks up a child. 728 * 729 * @returns Pointer to child node if found, NULL if not. 730 * @param pParent The parent node. 731 * @param pchName The name (not necessarily terminated). 732 * @param cchName The length of the name. 733 * @param piChild Where to store a child index suitable for 734 * passing to stamR3LookupNewChild when NULL is 735 * returned. 736 */ 737 static PSTAMLOOKUP stamR3LookupFindChild(PSTAMLOOKUP pParent, const char *pchName, uint32_t cchName, uint32_t *piChild) 738 { 739 uint32_t iChild = pParent->cChildren; 740 if (iChild > 4) 741 { 742 uint32_t iFirst = 0; 743 uint32_t iEnd = iChild; 744 iChild /= 2; 745 for (;;) 746 { 747 int iDiff = stamR3LookupCmp(pParent->papChildren[iChild], pchName, cchName); 748 if (!iDiff) 749 { 750 *piChild = iChild; 751 return pParent->papChildren[iChild]; 752 } 753 754 /* Split. */ 755 if (iDiff < 0) 756 { 757 iFirst = iChild + 1; 758 if (iFirst >= iEnd) 759 { 760 *piChild = iChild; 761 break; 762 } 763 } 764 else 765 { 766 if (iChild == iFirst) 767 { 768 *piChild = iChild ? iChild - 1 : 0; 769 break; 770 } 771 iEnd = iChild; 772 } 773 774 /* Calc next child. */ 775 iChild = (iEnd - iFirst) / 2 + iFirst; 776 } 777 return NULL; 778 } 779 780 /* 781 * Linear search. 782 */ 783 while (iChild-- > 0) 784 { 785 int iDiff = stamR3LookupCmp(pParent->papChildren[iChild], pchName, cchName); 786 if (iDiff <= 0) 787 { 788 *piChild = iChild; 789 return !iDiff ? pParent->papChildren[iChild] : NULL; 790 } 791 } 792 *piChild = 0; 793 return NULL; 794 } 795 796 797 /** 798 * Find the next sample description node. 799 * 800 * This is for use with insertion in the big list. 801 * 802 * @returns Pointer to the next sample description. NULL if not found (i.e. 803 * we're at the end of the list). 804 * @param pLookup The current node. 805 */ 806 static PSTAMDESC stamR3LookupFindNextWithDesc(PSTAMLOOKUP pLookup) 807 { 808 Assert(!pLookup->pDesc); 809 PSTAMLOOKUP pCur = pLookup; 810 uint32_t iCur = 0; 811 for (;;) 812 { 813 /* 814 * Check all children. 815 */ 816 uint32_t cChildren = pCur->cChildren; 817 if (iCur < cChildren) 818 { 819 PSTAMLOOKUP *papChildren = pCur->papChildren; 820 do 821 { 822 PSTAMLOOKUP pChild = pCur->papChildren[iCur]; 823 if (pChild->pDesc) 824 return pChild->pDesc; 825 826 if (pChild->cChildren > 0) 827 { 828 /* One level down. */ 829 iCur = 0; 830 pCur = pChild; 831 break; 832 } 833 } while (++iCur < cChildren); 834 } 835 else 836 { 837 /* One level up, resuming after the current. */ 838 iCur = pCur->iParent + 1; 839 pCur = pCur->pParent; 840 if (!pCur) 841 return NULL; 842 } 843 } 844 } 845 846 847 /** 848 * Increments the cDescInTree member of the given node an all ancestors. 849 * 850 * @param pLookup The lookup node. 851 */ 852 static void stamR3LookupIncUsage(PSTAMLOOKUP pLookup) 853 { 854 Assert(pLookup->pDesc); 855 856 PSTAMLOOKUP pCur = pLookup; 857 while (pCur != NULL) 858 { 859 pCur->cDescsInTree++; 860 pCur = pCur->pParent; 861 } 862 } 863 864 865 /** 866 * Descrements the cDescInTree member of the given node an all ancestors. 867 * 868 * @param pLookup The lookup node. 869 */ 870 static void stamR3LookupDecUsage(PSTAMLOOKUP pLookup) 871 { 872 Assert(!pLookup->pDesc); 873 874 PSTAMLOOKUP pCur = pLookup; 875 while (pCur != NULL) 876 { 877 Assert(pCur->cDescsInTree > 0); 878 pCur->cDescsInTree--; 879 pCur = pCur->pParent; 880 } 881 } 882 883 884 /** 885 * Frees empty lookup nodes if it's worth it. 886 * 887 * @param pLookup The lookup node. 888 */ 889 static void stamR3LookupMaybeFree(PSTAMLOOKUP pLookup) 890 { 891 Assert(!pLookup->pDesc); 892 893 /* 894 * Free between two and three levels of nodes. Freeing too much most 895 * likely wasted effort since we're either going to repopluate the tree 896 * or quit the whole thing. 897 */ 898 if (pLookup->cDescsInTree > 0) 899 return; 900 901 PSTAMLOOKUP pCur = pLookup->pParent; 902 if (!pCur) 903 return; 904 if (pCur->cDescsInTree > 0) 905 return; 906 PSTAMLOOKUP pParent = pCur->pParent; 907 if (pParent) 908 return; 909 910 if (pParent->cDescsInTree == 0 && pParent->pParent) 911 { 912 pCur = pParent; 913 pParent = pCur->pParent; 914 } 915 916 /* 917 * Remove pCur from pParent. 918 */ 919 PSTAMLOOKUP *papChildren = pParent->papChildren; 920 uint32_t cChildren = --pParent->cChildren; 921 for (uint32_t i = pCur->iParent; i < cChildren; i++) 922 { 923 PSTAMLOOKUP pChild = papChildren[i + 1]; 924 pChild->iParent = i; 925 papChildren[i] = pChild; 926 } 927 pCur->pParent = NULL; 928 929 /* 930 * Destroy pCur. 931 */ 932 stamR3LookupDestroyTree(pCur); 933 } 934 935 936 /** 937 * Destroys a lookup tree. 938 * 939 * This is used by STAMR3Term as well as stamR3LookupMaybeFree. 940 * 941 * @param pRoot The root of the tree (must have no parent). 942 */ 943 static void stamR3LookupDestroyTree(PSTAMLOOKUP pRoot) 944 { 945 Assert(pRoot); Assert(!pRoot->pParent); 946 PSTAMLOOKUP pLookup = pRoot; 947 for (;;) 948 { 949 uint32_t i = pLookup->cChildren; 950 if (i > 0) 951 { 952 /* 953 * Push child (with leaf optimization). 954 */ 955 PSTAMLOOKUP pChild = pLookup->papChildren[--i]; 956 if (pChild->cChildren != 0) 957 pLookup = pChild; 958 else 959 { 960 /* free leaves. */ 961 for (;;) 962 { 963 if (pChild->papChildren) 964 { 965 RTMemFree(pChild->papChildren); 966 pChild->papChildren = NULL; 967 } 968 RTMemFree(pChild); 969 970 /* next */ 971 if (i == 0) 972 { 973 pLookup->papChildren = 0; 974 break; 975 } 976 pChild = pLookup->papChildren[--i]; 977 if (pChild->cChildren != 0) 978 { 979 pLookup->cChildren = i + 1; 980 pLookup = pChild; 981 break; 982 } 983 } 984 } 985 } 986 else 987 { 988 /* 989 * Pop and free current. 990 */ 991 Assert(!pLookup->pDesc); 992 993 PSTAMLOOKUP pParent = pLookup->pParent; 994 RTMemFree(pLookup->papChildren); 995 pLookup->papChildren = NULL; 996 RTMemFree(pLookup); 997 998 pLookup = pParent; 999 if (!pLookup) 1000 break; 1001 pLookup->cChildren--; 1002 } 1003 } 1004 } 1005 1006 #endif /* STAM_WITH_LOOKUP_TREE */ 1007 579 1008 580 1009 … … 598 1027 STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc) 599 1028 { 1029 AssertReturn(pszName[0] == '/', VERR_INVALID_NAME); 1030 AssertReturn(pszName[1] != '/' && pszName[1], VERR_INVALID_NAME); 1031 uint32_t const cchName = (uint32_t)strlen(pszName); 1032 AssertReturn(cchName < 256, VERR_OUT_OF_RANGE); 1033 AssertReturn(pszName[cchName - 1] != '/', VERR_INVALID_NAME); 1034 AssertReturn(memchr(pszName, '\\', cchName) == NULL, VERR_INVALID_NAME); 1035 600 1036 STAM_LOCK_WR(pUVM); 601 1037 602 1038 /* 603 * Check if exists. 604 */ 605 #if 0 606 PSTAMDESC pPrev = pUVM->stam.s.pHint; 607 PSTAMDESC pCur = pPrev ? pPrev->pNext : NULL; 608 if (!pCur || strcmp(pCur->pszName, pszName) > 0) 609 { 610 pPrev = NULL; 611 pCur = pUVM->stam.s.pHead; 612 } 1039 * Look up the tree location, populating the lookup tree as we walk it. 1040 */ 1041 #ifdef STAM_WITH_LOOKUP_TREE 1042 PSTAMLOOKUP pLookup = pUVM->stam.s.pRoot; Assert(pLookup); 1043 uint32_t offName = 1; 1044 for (;;) 1045 { 1046 /* Get the next part of the path. */ 1047 const char *pszStart = &pszName[offName]; 1048 const char *pszEnd = strchr(pszStart, '/'); 1049 uint32_t cch = pszEnd ? (uint32_t)(pszEnd - pszStart) : cchName - offName; 1050 if (cch == 0) 1051 { 1052 STAM_UNLOCK_WR(pUVM); 1053 AssertMsgFailed(("No double or trailing slashes are allowed: '%s'\n", pszName)); 1054 return VERR_INVALID_NAME; 1055 } 1056 1057 /* Do the looking up. */ 1058 uint32_t iChild = 0; 1059 PSTAMLOOKUP pChild = stamR3LookupFindChild(pLookup, pszStart, cch, &iChild); 1060 if (!pChild) 1061 { 1062 pChild = stamR3LookupNewChild(pLookup, pszStart, cch, offName, iChild); 1063 if (!pChild) 1064 { 1065 STAM_UNLOCK_WR(pUVM); 1066 return VERR_NO_MEMORY; 1067 } 1068 } 1069 1070 /* Advance. */ 1071 pLookup = pChild; 1072 if (!pszEnd) 1073 break; 1074 offName += cch + 1; 1075 } 1076 if (pLookup->pDesc) 1077 { 1078 STAM_UNLOCK_WR(pUVM); 1079 AssertMsgFailed(("Duplicate sample name: %s\n", pszName)); 1080 return VERR_ALREADY_EXISTS; 1081 } 1082 1083 PSTAMDESC pCur = stamR3LookupFindNextWithDesc(pLookup); 1084 613 1085 #else 614 PSTAMDESC pPrev = NULL; 615 PSTAMDESC pCur = pUVM->stam.s.pHead; 616 #endif 617 while (pCur) 1086 PSTAMDESC pCur; 1087 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 618 1088 { 619 1089 int iDiff = strcmp(pCur->pszName, pszName); … … 628 1098 return VERR_ALREADY_EXISTS; 629 1099 } 630 631 /* next */ 632 pPrev = pCur; 633 pCur = pCur->pNext; 634 } 635 pUVM->stam.s.pHint = pPrev; 1100 } 1101 #endif 636 1102 637 1103 /* … … 640 1106 * Problematic chars are: !"#$%&'()*+,-. 641 1107 */ 1108 #ifdef VBOX_STRICT 642 1109 Assert(pszName[0] == '/'); 643 if (pPrev) 644 Assert(stamR3SlashCompare(pPrev->pszName, pszName) < 0); 645 if (pCur) 646 Assert(stamR3SlashCompare(pCur->pszName, pszName) > 0); 647 648 #ifdef VBOX_STRICT 1110 PSTAMDESC pPrev = pCur 1111 ? RTListGetPrev(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 1112 : RTListGetLast(&pUVM->stam.s.List, STAMDESC, ListEntry); 1113 Assert(!pPrev || strcmp(pszName, pPrev->pszName) > 0); 1114 Assert(!pCur || strcmp(pszName, pCur->pszName) < 0); 1115 Assert(!pPrev || stamR3SlashCompare(pPrev->pszName, pszName) < 0); 1116 Assert(!pCur || stamR3SlashCompare(pCur->pszName, pszName) > 0); 1117 649 1118 /* 650 1119 * Check alignment requirements. … … 701 1170 */ 702 1171 int rc; 703 size_t cchName = strlen(pszName) + 1; 704 size_t cchDesc = pszDesc ? strlen(pszDesc) + 1 : 0; 705 PSTAMDESC pNew = (PSTAMDESC)RTMemAlloc(sizeof(*pNew) + cchName + cchDesc); 1172 size_t cbDesc = pszDesc ? strlen(pszDesc) + 1 : 0; 1173 PSTAMDESC pNew = (PSTAMDESC)RTMemAlloc(sizeof(*pNew) + cchName + 1 + cbDesc); 706 1174 if (pNew) 707 1175 { 708 pNew->pszName = (char *)memcpy((char *)(pNew + 1), pszName, cchName );1176 pNew->pszName = (char *)memcpy((char *)(pNew + 1), pszName, cchName + 1); 709 1177 pNew->enmType = enmType; 710 1178 pNew->enmVisibility = enmVisibility; … … 720 1188 pNew->pszDesc = NULL; 721 1189 if (pszDesc) 722 pNew->pszDesc = (char *)memcpy((char *)(pNew + 1) + cchName, pszDesc, cchDesc); 723 724 pNew->pNext = pCur; 725 if (pPrev) 726 pPrev->pNext = pNew; 1190 pNew->pszDesc = (char *)memcpy((char *)(pNew + 1) + cchName + 1, pszDesc, cbDesc); 1191 1192 if (pCur) 1193 RTListNodeInsertBefore(&pCur->ListEntry, &pNew->ListEntry); 727 1194 else 728 pUVM->stam.s.pHead = pNew; 1195 RTListAppend(&pUVM->stam.s.List, &pNew->ListEntry); 1196 1197 #ifdef STAM_WITH_LOOKUP_TREE 1198 pNew->pLookup = pLookup; 1199 pLookup->pDesc = pNew; 1200 stamR3LookupIncUsage(pLookup); 1201 #endif 729 1202 730 1203 stamR3ResetOne(pNew, pUVM->pVM); … … 759 1232 */ 760 1233 int rc = VERR_INVALID_HANDLE; 761 PSTAMDESC pPrev = NULL; 762 PSTAMDESC pCur = pUVM->stam.s.pHead; 763 while (pCur) 1234 PSTAMDESC pCur, pNext; 1235 RTListForEachSafe(&pUVM->stam.s.List, pCur, pNext, STAMDESC, ListEntry) 764 1236 { 765 1237 if (pCur->u.pv == pvSample) 766 1238 { 767 void *pvFree = pCur; 768 pCur = pCur->pNext; 769 if (pPrev) 770 pPrev->pNext = pCur; 771 else 772 pUVM->stam.s.pHead = pCur; 773 774 RTMemFree(pvFree); 1239 RTListNodeRemove(&pCur->ListEntry); 1240 #ifdef STAM_WITH_LOOKUP_TREE 1241 pCur->pLookup->pDesc = NULL; /** @todo free lookup nodes once it's working. */ 1242 stamR3LookupDecUsage(pCur->pLookup); 1243 stamR3LookupMaybeFree(pCur->pLookup); 1244 #endif 1245 RTMemFree(pCur); 775 1246 rc = VINF_SUCCESS; 776 continue; 777 } 778 779 /* next */ 780 pPrev = pCur; 781 pCur = pCur->pNext; 1247 } 782 1248 } 783 1249 … … 1677 2143 1678 2144 STAM_LOCK_RD(pUVM); 1679 PSTAMDESC pCur = pUVM->stam.s.pHead;1680 while (pCur)2145 PSTAMDESC pCur; 2146 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 1681 2147 { 1682 2148 rc = pfnCallback(pCur, pvArg); 1683 2149 if (rc) 1684 2150 break; 1685 1686 /* next */1687 pCur = pCur->pNext;1688 2151 } 1689 2152 STAM_UNLOCK_RD(pUVM); … … 1702 2165 * Note that it's doing exact matching. Organizing the samples in a tree would speed up thing 1703 2166 * no end (at least for debug and profile builds). */ 1704 for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext) 2167 PSTAMDESC pCur; 2168 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 2169 { 1705 2170 if (RTStrSimplePatternMatch(pszPat, pCur->pszName)) 1706 2171 { … … 1709 2174 break; 1710 2175 } 2176 } 1711 2177 STAM_UNLOCK_RD(pUVM); 1712 2178 } … … 1734 2200 STAM_LOCK_RD(pUVM); 1735 2201 unsigned iExpression = 0; 1736 for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext) 2202 PSTAMDESC pCur; 2203 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 2204 { 1737 2205 if (stamR3MultiMatch(papszExpressions, cExpressions, &iExpression, pCur->pszName)) 1738 2206 { … … 1741 2209 break; 1742 2210 } 2211 } 1743 2212 STAM_UNLOCK_RD(pUVM); 1744 2213 … … 1933 2402 */ 1934 2403 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM); 1935 if ( !pUVM->stam.s.pHead)2404 if (RTListIsEmpty(&pUVM->stam.s.List)) 1936 2405 return DBGCCmdHlpFail(pCmdHlp, pCmd, "No statistics present"); 1937 2406 … … 1976 2445 */ 1977 2446 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM); 1978 if ( !pUVM->stam.s.pHead)2447 if (RTListIsEmpty(&pUVM->stam.s.List)) 1979 2448 return DBGCCmdHlpFail(pCmdHlp, pCmd, "No statistics present"); 1980 2449 -
trunk/src/VBox/VMM/include/STAMInternal.h
r46438 r46443 24 24 #include <VBox/vmm/gvmm.h> 25 25 #include <VBox/vmm/gmm.h> 26 #include <iprt/list.h> 26 27 #include <iprt/semaphore.h> 27 28 … … 36 37 */ 37 38 39 /** Enables the lookup tree. 40 * This is an optimization for speeding up registration as well as query. */ 41 #define STAM_WITH_LOOKUP_TREE 42 43 44 /** Pointer to sample descriptor. */ 45 typedef struct STAMDESC *PSTAMDESC; 46 /** Pointer to a sample lookup node. */ 47 typedef struct STAMLOOKUP *PSTAMLOOKUP; 48 49 /** 50 * Sample lookup node. 51 */ 52 typedef struct STAMLOOKUP 53 { 54 /** The parent lookup record. This is NULL for the root node. */ 55 PSTAMLOOKUP pParent; 56 /** Array of children (using array for binary searching). */ 57 PSTAMLOOKUP *papChildren; 58 /** Pointer to the description node, if any. */ 59 PSTAMDESC pDesc; 60 /** Number of decentants with descriptors. (Use for freeing up sub-trees.) */ 61 uint32_t cDescsInTree; 62 /** The number of children. */ 63 uint16_t cChildren; 64 /** The index in the parent paChildren array. UINT16_MAX for the root node. */ 65 uint16_t iParent; 66 /** The path offset. */ 67 uint16_t off; 68 /** The size of the path component. */ 69 uint16_t cch; 70 /** The name (variable size). */ 71 char szName[1]; 72 } STAMLOOKUP; 73 74 38 75 /** 39 76 * Sample descriptor. … … 41 78 typedef struct STAMDESC 42 79 { 43 /** Pointer to the next sample. */ 44 struct STAMDESC *pNext; 80 /** Our entry in the big linear list. */ 81 RTLISTNODE ListEntry; 82 /** Pointer to our lookup node. */ 83 PSTAMLOOKUP pLookup; 45 84 /** Sample name. */ 46 85 const char *pszName; … … 88 127 const char *pszDesc; 89 128 } STAMDESC; 90 /** Pointer to sample descriptor. */91 typedef STAMDESC *PSTAMDESC;92 /** Pointer to const sample descriptor. */93 typedef const STAMDESC *PCSTAMDESC;94 129 95 130 … … 99 134 typedef struct STAMUSERPERVM 100 135 { 101 /** Pointer to the first sample. */ 102 R3PTRTYPE(PSTAMDESC) pHead; 103 /** Lookup hint (pPrev value). */ 104 R3PTRTYPE(PSTAMDESC) pHint; 105 /** RW Lock for the list. */ 136 /** List of samples. */ 137 RTLISTANCHOR List; 138 /** Root of the lookup tree. */ 139 PSTAMLOOKUP pRoot; 140 141 /** RW Lock for the list and tree. */ 106 142 RTSEMRW RWSem; 107 /** Alignment padding. */108 RTR3PTR Alignment;109 143 110 144 /** The copy of the GVMM statistics. */ … … 118 152 GMMSTATS GMMStats; 119 153 } STAMUSERPERVM; 154 #ifdef IN_RING3 120 155 AssertCompileMemberAlignment(STAMUSERPERVM, GMMStats, 8); 156 #endif 121 157 122 158 /** Pointer to the STAM data kept in the UVM. */
Note:
See TracChangeset
for help on using the changeset viewer.