VirtualBox

Changeset 93671 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 9, 2022 11:42:46 PM (3 years ago)
Author:
vboxsync
Message:

IPRT/hardavl: Initial adaption of the old AVL code into something a little more sturdy and suitable for manging data shared between kernel and user space. Needs more testing and possibly more use of 'volatile'. bugref:10093

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/tstRTAvl.cpp

    r93115 r93671  
    3030*********************************************************************************************************************************/
    3131#include <iprt/avl.h>
     32#include <iprt/cpp/hardavlrange.h>
    3233
    3334#include <iprt/asm.h>
     
    10241025
    10251026
     1027/*********************************************************************************************************************************
     1028*   RTCHardAvlRangeTreeGCPhys                                                                                                    *
     1029*********************************************************************************************************************************/
     1030
     1031typedef struct TESTNODE
     1032{
     1033    RTGCPHYS Key, KeyLast;
     1034    uint32_t idxLeft, idxRight;
     1035    uint8_t  cHeight;
     1036} MYTESTNODE;
     1037
     1038static DECLCALLBACK(int) hardAvlRangeTreeGCPhysEnumCallbackAscBy4(TESTNODE *pNode, void *pvUser)
     1039{
     1040    PRTGCPHYS pExpect = (PRTGCPHYS)pvUser;
     1041    if (pNode->Key != *pExpect)
     1042        RTTestIFailed("Key=%RGp, expected %RGp\n", pNode->Key, *pExpect);
     1043    *pExpect = pNode->Key + 4;
     1044    return VINF_SUCCESS;
     1045}
     1046
     1047/** @return meaningless, just for return RTTestIFailed(); */
     1048int hardAvlRangeTreeGCPhys(RTTEST hTest)
     1049{
     1050    RTTestISubF("RTCHardAvlRangeTreeGCPhys");
     1051
     1052    /*
     1053     * Tree and allocator variables.
     1054     */
     1055    RTCHardAvlTreeSlabAllocator<MYTESTNODE>   Allocator;
     1056    RTCHardAvlRangeTree<MYTESTNODE, RTGCPHYS> Tree(&Allocator);
     1057    AssertCompileSize(Tree, sizeof(uint32_t) * 2);
     1058    AssertCompileSize(Allocator, sizeof(void *) * 2 + sizeof(uint32_t) * 4);
     1059
     1060    /* Initialize the allocator with a decent slab of memory. */
     1061    const uint32_t cItems = 16384;
     1062    void *pvItems;
     1063    RTTESTI_CHECK_RC_RET(RTTestGuardedAlloc(hTest, sizeof(MYTESTNODE) * cItems,
     1064                                            sizeof(uint64_t), false, &pvItems), VINF_SUCCESS, 1);
     1065    void *pbmBitmap;
     1066    RTTESTI_CHECK_RC_RET(RTTestGuardedAlloc(hTest, RT_ALIGN_32(cItems, 64) / 64 * 8,
     1067                                            sizeof(uint64_t), false, &pbmBitmap), VINF_SUCCESS, 1);
     1068    Allocator.initSlabAllocator(cItems, (TESTNODE *)pvItems, (uint64_t *)pbmBitmap);
     1069
     1070    /*
     1071     * Simple linear insert, get and remove.
     1072     */
     1073    /* insert */
     1074    for (unsigned i = 0; i < 65536; i += 4)
     1075    {
     1076        MYTESTNODE *pNode = Allocator.allocateNode();
     1077        if (!pNode)
     1078            return RTTestIFailed("out of nodes: i=%#x", i);
     1079        pNode->Key = i;
     1080        pNode->KeyLast = i + 3;
     1081        int rc = Tree.insert(&Allocator, pNode);
     1082        if (rc != VINF_SUCCESS)
     1083            RTTestIFailed("linear insert i=%#x failed: %Rrc", i, rc);
     1084
     1085        /* look it up again immediately */
     1086        for (unsigned j = 0; j < 4; j++)
     1087        {
     1088            MYTESTNODE *pNode2;
     1089            rc = Tree.lookup(&Allocator, i + j, &pNode2);
     1090            if (rc != VINF_SUCCESS || pNode2 != pNode)
     1091                return RTTestIFailed("get after insert i=%#x j=%#x: %Rrc pNode=%p pNode2=%p", i, j, rc, pNode, pNode2);
     1092        }
     1093
     1094        /* Do negative inserts if we've got more free nodes. */
     1095        if (i / 4 + 1 < cItems)
     1096        {
     1097            MYTESTNODE *pNode2 = Allocator.allocateNode();
     1098            if (!pNode2)
     1099                return RTTestIFailed("out of nodes: i=%#x (#2)", i);
     1100            RTTESTI_CHECK(pNode2 != pNode);
     1101
     1102            *pNode2 = *pNode;
     1103            for (unsigned j = i >= 32 ? i - 32 : 0; j <= i + 3; j++)
     1104            {
     1105                for (unsigned k = i; k < i + 32; k++)
     1106                {
     1107                    pNode2->Key     = RT_MIN(j, k);
     1108                    pNode2->KeyLast = RT_MAX(k, j);
     1109                    rc = Tree.insert(&Allocator, pNode2);
     1110                    if (rc != VERR_ALREADY_EXISTS)
     1111                        return RTTestIFailed("linear negative insert: %Rrc, expected VERR_ALREADY_EXISTS; i=%#x j=%#x k=%#x; Key2=%RGp KeyLast2=%RGp vs Key=%RGp KeyLast=%RGp",
     1112                                             rc, i, j, k, pNode2->Key, pNode2->KeyLast, pNode->Key, pNode->KeyLast);
     1113                }
     1114                if (j == 0)
     1115                    break;
     1116            }
     1117
     1118            rc = Allocator.freeNode(pNode2);
     1119            if (rc != VINF_SUCCESS)
     1120                return RTTestIFailed("freeNode(pNode2=%p) failed: %Rrc (i=%#x)", pNode2, rc, i);
     1121        }
     1122    }
     1123
     1124    /* do gets. */
     1125    for (unsigned i = 0; i < 65536; i += 4)
     1126    {
     1127        MYTESTNODE *pNode;
     1128        int rc = Tree.lookup(&Allocator, i, &pNode);
     1129        if (rc != VINF_SUCCESS || pNode == NULL)
     1130            return RTTestIFailed("linear get i=%#x: %Rrc pNode=%p", i, rc, pNode);
     1131        if (i < pNode->Key || i > pNode->KeyLast)
     1132            return RTTestIFailed("linear get i=%#x Key=%RGp KeyLast=%RGp\n", i, pNode->Key, pNode->KeyLast);
     1133
     1134        for (unsigned j = 1; j < 4; j++)
     1135        {
     1136            MYTESTNODE *pNode2;
     1137            rc = Tree.lookup(&Allocator, i + j, &pNode2);
     1138            if (rc != VINF_SUCCESS || pNode2 != pNode)
     1139                return RTTestIFailed("linear get i=%#x j=%#x: %Rrc pNode=%p pNode2=%p", i, j, rc, pNode, pNode2);
     1140        }
     1141    }
     1142
     1143    /* negative get */
     1144    for (unsigned i = 65536; i < 65536 * 2; i += 1)
     1145    {
     1146        MYTESTNODE *pNode = (MYTESTNODE *)(uintptr_t)i;
     1147        int rc = Tree.lookup(&Allocator, i, &pNode);
     1148        if (rc != VERR_NOT_FOUND || pNode != NULL)
     1149            return RTTestIFailed("linear negative get i=%#x: %Rrc pNode=%p, expected VERR_NOT_FOUND and NULL", i, rc, pNode);
     1150    }
     1151
     1152    /* enumerate */
     1153    {
     1154        RTGCPHYS Expect = 0;
     1155        int rc = Tree.doWithAllFromLeft(&Allocator, hardAvlRangeTreeGCPhysEnumCallbackAscBy4, &Expect);
     1156        if (rc != VINF_SUCCESS)
     1157            RTTestIFailed("enumeration after linear insert failed: %Rrc", rc);
     1158    }
     1159
     1160    /* remove */
     1161    for (unsigned i = 0, j = 0; i < 65536; i += 4, j += 3)
     1162    {
     1163        MYTESTNODE *pNode;
     1164        int rc = Tree.remove(&Allocator, i + (j % 4), &pNode);
     1165        if (rc != VINF_SUCCESS || pNode == NULL)
     1166            return RTTestIFailed("linear remove(%#x): %Rrc pNode=%p", i + (j % 4), rc, pNode);
     1167        if (i < pNode->Key || i > pNode->KeyLast)
     1168            return RTTestIFailed("linear remove i=%#x Key=%RGp KeyLast=%RGp\n", i, pNode->Key, pNode->KeyLast);
     1169
     1170        memset(pNode, 0xcc, sizeof(*pNode));
     1171        Allocator.freeNode(pNode);
     1172
     1173        /* negative */
     1174        for (unsigned k = i; k < i + 4; k++)
     1175        {
     1176            pNode = (MYTESTNODE *)(uintptr_t)k;
     1177            rc = Tree.remove(&Allocator, k, &pNode);
     1178            if (rc != VERR_NOT_FOUND || pNode != NULL)
     1179                return RTTestIFailed("linear negative remove(%#x): %Rrc pNode=%p", k, rc, pNode);
     1180        }
     1181    }
     1182
     1183    /*
     1184     * Randomized stuff.
     1185     */
     1186    /** @todo add randomized testing step.  Split the address space up into equal
     1187     *        portition and pick what to insert/remove/lookup using a random
     1188     *        function against a insertion status bitmap. */
     1189
     1190    return 0;
     1191}
     1192
     1193
    10261194int main()
    10271195{
     
    10661234    avlrogcphys();
    10671235    avlul();
     1236    hardAvlRangeTreeGCPhys(hTest);
    10681237
    10691238    /*
Note: See TracChangeset for help on using the changeset viewer.

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