Annotation of coherent/f/etc/conf/streams/src/st_test.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include <stdlib.h>
                      3: 
                      4: #include <kernel/st_alloc.h>
                      5: 
                      6: 
                      7: /*
                      8:  * Work around some deficiencies in the UNIX library w.r.t. Borland.
                      9:  */
                     10: 
                     11: #if    __BORLANDC__
                     12: 
                     13: #define        RANDOM(n)       random (n)
                     14: #define        RANDOMIZE()     randomize ()
                     15: 
                     16: #else
                     17: 
                     18: /*
                     19:  * While this function is not part of POSIX, many implementations provide
                     20:  * it; random (n) returns a random integer in the range of 0 to (n - 1).
                     21:  *
                     22:  * Note that (rand () % n) is not a sufficient implementation, as the
                     23:  * distribution of (rand () % n) will not be uniform for n not a power of 2.
                     24:  * For instance, with n = 2*RAND_MAX/3, using the modulus will cause the
                     25:  * numbers from 0 to RAND_MAX/2 - 1 to occur twice as often as the second
                     26:  * half of the range.
                     27:  *
                     28:  * The expression "(int) ((long) rand () * range / (RAND_MAX + 1))" as used
                     29:  * by Borland works to distribute the error uniformly across the range 0 to
                     30:  * n-1, but still can cause certain numbers to have a higher probability
                     31:  * than their neighbours.
                     32:  *
                     33:  * The following system minimizes the error at the expense of execution
                     34:  * time by simply throwing away those numbers that cause the error, ie those
                     35:  * numbers from RAND_MAX down to RAND_MAX - ((RAND_MAX + 1) % n). A more
                     36:  * efficient system might use more bits from the LCG, but this works fine.
                     37:  */
                     38: 
                     39: static int RANDOM (int range) {
                     40:        int error, num;
                     41: 
                     42:        if (range <= 0)
                     43:                return 0;
                     44: 
                     45:        error = ((unsigned) RAND_MAX + 1) % range;
                     46: 
                     47:        while ((num = rand ()) > RAND_MAX - error)
                     48:                ;
                     49: 
                     50:        return num % range;
                     51: }
                     52: 
                     53: #include <time.h>
                     54: 
                     55: /*
                     56:  * And similarly for the randomize () function, which kicks off random number
                     57:  * generation.
                     58:  */
                     59: 
                     60: static void RANDOMIZE (void) {
                     61:        srand ((int) time (NULL));
                     62: }
                     63: 
                     64: #endif /* ! __BORLANDC__ */
                     65: 
                     66: 
                     67: /*
                     68:  * Dump some arena internals out...
                     69:  */
                     70: 
                     71: void st_dump (_ST_HEAP_CONTROL_P q) {
                     72:        _ST_ADDR_T      scan = _ST_HEAP_FIRST (q, 0);
                     73:        int     count, size, cntl;
                     74: 
                     75:        do {
                     76:                size = count = 0;
                     77:                while (! _ST_BLOCK_FREE (cntl = _ST_BLOCK_CONTROL (q, scan))) {
                     78:                         size += _ST_BLOCK_SIZE (cntl);
                     79:                        count ++;
                     80:                        if (_ST_HEAP_NEXT (scan, cntl) >= q->_arena_end)
                     81:                                break;
                     82:                        scan = _ST_HEAP_NEXT (scan, cntl);
                     83:                }
                     84:                printf ("%d allocated blocks of total size %d\n", count, size);
                     85: 
                     86:                if (! _ST_BLOCK_FREE (cntl))
                     87:                        break;
                     88: 
                     89:                size = count = 0;
                     90:                while (_ST_BLOCK_FREE (cntl = _ST_BLOCK_CONTROL (q, scan))) {
                     91:                        size += _ST_BLOCK_SIZE (cntl);
                     92:                        count ++;
                     93:                        if (_ST_HEAP_NEXT (scan, cntl) >= q->_arena_end)
                     94:                                break;
                     95:                        scan = _ST_HEAP_NEXT (scan, cntl);
                     96:                }
                     97:                printf ("%d free blocks of size %d\n", count, size);
                     98:        } while (_ST_HEAP_NEXT (scan, cntl) < q->_arena_end);
                     99: }
                    100: 
                    101: /*
                    102:  * Dump a small selection of buckets in great detail.
                    103:  */
                    104: 
                    105: void st_detail (_ST_HEAP_CONTROL_P q, int frombkt, int tobkt) {
                    106:        _ST_ADDR_T      scan = _ST_HEAP_FIRST (q, frombkt);
                    107:        int     i;
                    108: 
                    109:        while (scan < _ST_HEAP_FIRST (q, tobkt + 1)) {
                    110:                if ((i = _ST_HEAP_BUCKET (q, scan)) >= frombkt)
                    111:                        while (frombkt <= i)
                    112:                                printf ("\nBucket %d, %d biggest free, entry @ %04x : ",
                    113:                                        frombkt ++,
                    114:                                        _ST_HEAP_BIGGEST (q, frombkt + q->_buckets_inuse),
                    115:                                        scan);
                    116:                i = _ST_BLOCK_CONTROL (q, scan);
                    117:                printf (_ST_BLOCK_FREE (i) ? "Free %04x (%d) : " :
                    118:                                             "Used %04x (%d) : ",
                    119:                        scan, _ST_BLOCK_SIZE (i));
                    120:                scan = _ST_HEAP_NEXT (scan, i);
                    121:        }
                    122: }
                    123: 
                    124: 
                    125: /*
                    126:  * An assertion mechanism for testing the allocator.
                    127:  */
                    128: 
                    129: #define        ASSERT(q,x,i)   (! (x) ? st_fatal (q,i, __LINE__) : (void) 0)
                    130: 
                    131: static void st_fatal (_ST_HEAP_CONTROL_P q, int i, int line) {
                    132: 
                    133:        printf ("Assertion failure at line %d of file " __FILE__ "\n", line);
                    134:        printf ("Iteration number #%d\n", i);
                    135: 
                    136:        st_dump (q);
                    137: 
                    138:        abort ();
                    139: }
                    140: 
                    141: 
                    142: /*
                    143:  * Exercise the heap allocator. We exercise the allocator down to the last
                    144:  * byte, and define the following relationships so we can assume that by the
                    145:  * time we have done TEST_ALLOCS allocations of TEST_ALLOC_SIZE, then we have
                    146:  * consumed all free memory.
                    147:  *
                    148:  * The _ST_WORD_T factor in the TOTALWORDS calculation is for the block
                    149:  * headers used internally by the allocator. The _ST_ADDR_T factor is for the
                    150:  * addr [] array, which is also taken from the managed area. The "+ 2" factor
                    151:  * is for the block headers for (i) the dummy block at the start of the arena
                    152:  * and (ii) the block header for the addr [] block.
                    153:  */
                    154: 
                    155: #define        TEST_ALLOCS     2000            /* number of allocations */
                    156: #define        TEST_ALLOC_SIZE 16              /* in bytes */
                    157: #define        SEGMENTS        256             /* how many partitions in the space */
                    158: 
                    159: #define        TOTALWORDS      (TEST_ALLOCS * (TEST_ALLOC_SIZE + sizeof (_ST_WORD_T)\
                    160:                                        + sizeof (_ST_ADDR_T)) / sizeof (_ST_WORD_T)\
                    161:                         + 2)
                    162: 
                    163: void main (int argc, char ** argv) {
                    164:        _ST_HEAP_CONTROL_P q;
                    165:        void * mem;
                    166:        _ST_ADDR_T * addr;
                    167:        int i, base, leave;
                    168:        int forward = 0, back = 0, shuffle = 1;
                    169:        int growup = 1, growdown = 1, growboth = 1, growmove = 1, shrink = 1;
                    170: 
                    171:        RANDOMIZE ();
                    172: 
                    173:        printf ("TOTALWORDS = %d\n", TOTALWORDS);
                    174: 
                    175:        for (i = 1 ; i < argc ; i ++)
                    176:                if (argv [i][0] == '-')
                    177:                        switch (argv [i][1]) {
                    178: 
                    179:                        case 'f':
                    180:                                forward = argv [i][2] == 0 ? 1 : atoi (argv [i] + 2);
                    181:                                break;
                    182: 
                    183:                        case 'b':
                    184:                                back = argv [i][2] == 0 ? 1 : atoi (argv [i] + 2);
                    185:                                break;
                    186: 
                    187:                        case 'r':
                    188:                                shuffle = argv [i][2] == 0 ? 1 : atoi (argv [i] + 2);
                    189:                                break;
                    190: 
                    191:                        case 'l':
                    192:                                leave = argv [i][2] == 0 ? 1 : atoi (argv [i] + 2);
                    193:                                break;
                    194:                        }
                    195: 
                    196:        q = (_ST_HEAP_CONTROL_P) malloc (_ST_HEAP_CONTROL_SIZE (SEGMENTS));
                    197:        mem = malloc (TOTALWORDS * sizeof (_ST_WORD_T));
                    198: 
                    199:        st_ctor (q, SEGMENTS, TOTALWORDS, (_ST_ADDR_T) mem);
                    200: 
                    201:        st_assert (q);
                    202: 
                    203:        printf ("Using qheap : ");
                    204: 
                    205:        /*
                    206:         * Initially, why not get this space from the test arena ?
                    207:         */
                    208: 
                    209:        addr = (_ST_ADDR_T *) st_new (q, TEST_ALLOCS * sizeof (* addr));
                    210: 
                    211: 
                    212:        /*
                    213:         * Exercises for realloc (), growing blocks up.
                    214:         */
                    215: 
                    216:        while (growup -- > 0) {
                    217:                for (i = 0 ; i < TEST_ALLOCS ; i ++) {
                    218:                        addr [i] = st_new (q, TEST_ALLOC_SIZE);
                    219:                        ASSERT (q, addr [i] != NULL, i);
                    220:                }
                    221: 
                    222:                for (i = 0 ; i < TEST_ALLOCS ; i += 2) {
                    223:                        ASSERT (q, st_disp (q, addr [i + 1]
                    224:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    225: 
                    226:                        addr [i + 1] = st_realloc (q, addr [i], 2 * TEST_ALLOC_SIZE
                    227:                                                   ST_FREE_SIZE (TEST_ALLOC_SIZE));
                    228:                        ASSERT (q, addr [i + 1] == addr [i], i);
                    229: 
                    230:                        ASSERT (q, st_disp (q, addr [i]
                    231:                                         ST_FREE_SIZE (2 * TEST_ALLOC_SIZE)) == 0, i);
                    232:                }
                    233:        }
                    234: 
                    235:        st_dump (q);
                    236: 
                    237: 
                    238:        /*
                    239:         * Exercises for realloc (), growing blocks down.
                    240:         */
                    241: 
                    242:        while (growdown -- > 0) {
                    243:                _ST_ADDR_T      temp;
                    244: 
                    245:                for (i = 0 ; i < TEST_ALLOCS ; i ++) {
                    246:                        addr [i] = st_new (q, TEST_ALLOC_SIZE);
                    247:                        ASSERT (q, addr [i] != NULL, i);
                    248:                }
                    249: 
                    250:                temp = addr [0];
                    251: 
                    252:                for (i = 0 ; i < TEST_ALLOCS - 1 ; i += 2) {
                    253:                        ASSERT (q, st_disp (q, addr [i]
                    254:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    255: 
                    256:                        /* put a pattern in the block to be moved */
                    257: 
                    258:                        * addr [i + 1] = (_ST_WORD_T) addr [i + 1];
                    259: 
                    260:                        ASSERT (q,
                    261:                                st_realloc (q, addr [i + 1], 2 * TEST_ALLOC_SIZE
                    262:                                            ST_FREE_SIZE (TEST_ALLOC_SIZE))
                    263:                                == temp, i);
                    264: 
                    265:                        /* check that the data was moved correctly */
                    266: 
                    267:                        ASSERT (q, * temp == (_ST_WORD_T) addr [i + 1], i);
                    268: 
                    269:                        ASSERT (q, st_disp (q, temp
                    270:                                         ST_FREE_SIZE (2 * TEST_ALLOC_SIZE)) == 0, i);
                    271: 
                    272:                        if (st_assert (q) != 0) {
                    273:                                printf ("error %s, i = %d\n",
                    274:                                        _ST_HEAP_ERROR (q), i);
                    275:                                st_dump (q);
                    276:                                return;
                    277:                        }
                    278: 
                    279:                }
                    280:        }
                    281: 
                    282:        st_dump (q);
                    283: 
                    284: 
                    285:        /*
                    286:         * Exercises for realloc (), growing blocks both up and down.
                    287:         */
                    288: 
                    289:        while (growboth -- > 0) {
                    290: 
                    291:                for (i = 0 ; i < TEST_ALLOCS ; i ++) {
                    292:                        addr [i] = st_new (q, TEST_ALLOC_SIZE);
                    293:                        ASSERT (q, addr [i] != NULL, i);
                    294:                }
                    295: 
                    296:                for (i = 0 ; i < TEST_ALLOCS - 3 ; i += 4) {
                    297:                        ASSERT (q, st_disp (q, addr [i]
                    298:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    299: 
                    300:                        if (st_assert (q) != 0) {
                    301:                                printf ("st_disp () #1 error %s, i = %d\n",
                    302:                                        _ST_HEAP_ERROR (q), i);
                    303:                                st_dump (q);
                    304:                                return;
                    305:                        }
                    306: 
                    307:                        ASSERT (q, st_disp (q, addr [i + 2]
                    308:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    309: 
                    310:                        if (st_assert (q) != 0) {
                    311:                                printf ("st_disp () #2 error %s, i = %d\n",
                    312:                                        _ST_HEAP_ERROR (q), i);
                    313:                                st_dump (q);
                    314:                                return;
                    315:                        }
                    316: 
                    317:                        /* put a pattern in the block to be moved */
                    318: 
                    319:                        * addr [i + 1] = (_ST_WORD_T) addr [i + 1];
                    320: 
                    321:                        ASSERT (q, st_realloc (q, addr [i + 1], 3 * TEST_ALLOC_SIZE
                    322:                                            ST_FREE_SIZE (TEST_ALLOC_SIZE))
                    323:                                == addr [i], i);
                    324: 
                    325:                        /* check that the data was moved correctly */
                    326: 
                    327:                        ASSERT (q, * addr [i] == (_ST_WORD_T) addr [i + 1], i);
                    328: 
                    329:                        if (st_assert (q) != 0) {
                    330:                                printf ("error %s, i = %d\n",
                    331:                                        _ST_HEAP_ERROR (q), i);
                    332:                                st_dump (q);
                    333:                                return;
                    334:                        }
                    335:                }
                    336: 
                    337:                for (i = 0 ; i < TEST_ALLOCS - 3 ; i += 4) {
                    338:                        ASSERT (q, st_disp (q, addr [i]
                    339:                                         ST_FREE_SIZE (3 * TEST_ALLOC_SIZE)) == 0, i);
                    340:                        ASSERT (q, st_disp (q, addr [i + 3]
                    341:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    342:                }
                    343:        }
                    344: 
                    345:        st_dump (q);
                    346: 
                    347: 
                    348:        /*
                    349:         * Perform a given number of allocations and shuffled decallocations,
                    350:         * leaving behind a certain number of allocated blocks to clutter the
                    351:         * arena for the next set.
                    352:         */
                    353: 
                    354:        leave = base = 0;
                    355:        while (shuffle -- > 0) {
                    356:                for (i = base ; i < TEST_ALLOCS ; i ++) {
                    357:                        addr [i] = st_new (q, TEST_ALLOC_SIZE);
                    358:                        if (st_assert (q) != 0) {
                    359:                                printf ("Alloc error %s, %d blocks remaining",
                    360:                                        _ST_HEAP_ERROR (q), i);
                    361:                                return;
                    362:                        }
                    363:                        ASSERT (q, addr [i] != NULL, i);
                    364:                }
                    365: 
                    366:                base = shuffle > 0 ? leave : 0;
                    367: 
                    368:                for (i = TEST_ALLOCS ; i -- > base ;) {
                    369: 
                    370:                        /*
                    371:                         * Pick an element to free, then exchange that for
                    372:                         * the last element, thereby shortening the list.
                    373:                         */
                    374: 
                    375:                        int elem = RANDOM (i + 1);
                    376:                        ASSERT (q, st_disp (q, addr [elem]
                    377:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    378:                        if (st_assert (q) != 0) {
                    379:                                printf ("Free error %s, %d blocks remaining",
                    380:                                        _ST_HEAP_ERROR (q), i);
                    381:                                return;
                    382:                        }
                    383:                         addr [elem] = addr [i];
                    384:                }
                    385:        }
                    386: 
                    387:         st_dump (q);
                    388: 
                    389: 
                    390:        /*
                    391:         * Deallocate from the bottom to the top.
                    392:         */
                    393: 
                    394:        while (forward -- > 0) {
                    395:                for (i = 0 ; i < TEST_ALLOCS ; i ++) {
                    396:                        addr [i] = st_new (q, TEST_ALLOC_SIZE);
                    397:                        ASSERT (q, addr [i] != NULL, i);
                    398:                }
                    399: 
                    400:                for (i = 0 ; i < TEST_ALLOCS ; i ++)
                    401:                        ASSERT (q, st_disp (q, addr [i]
                    402:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    403:        }
                    404: 
                    405: 
                    406:        /*
                    407:         * Deallocate from the top to the bottom.
                    408:         */
                    409: 
                    410:        while (back -- > 0) {
                    411:                for (i = 0 ; i < TEST_ALLOCS ; i ++) {
                    412:                        addr [i] = st_new (q, TEST_ALLOC_SIZE);
                    413:                        ASSERT (q, addr [i] != NULL, i);
                    414:                }
                    415: 
                    416:                for (i = TEST_ALLOCS ; i -- > 0 ;)
                    417:                        ASSERT (q, st_disp (q, addr [i]
                    418:                                         ST_FREE_SIZE (TEST_ALLOC_SIZE)) == 0, i);
                    419:        }
                    420: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.