Home | History | Annotate | Download | only in tests
      1 #include <unistd.h>
      2 #include "tests/sys_mman.h"
      3 #include <assert.h>
      4 #include <stdlib.h>
      5 
      6 #include "../memcheck.h"
      7 
      8 #define SUPERBLOCK_SIZE 100000
      9 #define REDZONE_SIZE 8
     10 
     11 static const int USE_MMAP = 0;
     12 
     13 typedef struct _level_list
     14 {
     15    struct _level_list *next;
     16    char *where;
     17    // Padding ensures the struct is the same size on 32-bit and 64-bit
     18    // machines.
     19    char padding[16 - 2*sizeof(char*)];
     20 } level_list;
     21 
     22 typedef struct _pool {
     23    char *mem;
     24    char *where;
     25    level_list *levels;
     26    int size, left;
     27    // Padding ensures the struct is the same size on 32-bit and 64-bit
     28    // machines.
     29    char padding[24 - 3*sizeof(char*)];
     30 } pool;
     31 
     32 pool *make_pool()
     33 {
     34    pool *p;
     35 
     36    if(USE_MMAP) {
     37       p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC,
     38                        MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     39       p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE,
     40                                        PROT_READ|PROT_WRITE|PROT_EXEC,
     41                                        MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     42    } else {
     43       p = (pool *)malloc(sizeof(pool));
     44       p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE);
     45    }
     46 
     47    p->size = p->left = SUPERBLOCK_SIZE;
     48    p->levels = NULL;
     49    (void) VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE);
     50    return p;
     51 }
     52 
     53 void push(pool *p)
     54 {
     55    level_list *l;
     56 
     57    if(USE_MMAP)
     58       l = (level_list *)mmap(0, sizeof(level_list),
     59                              PROT_READ|PROT_WRITE|PROT_EXEC,
     60                              MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     61    else
     62       l = (level_list *)malloc(sizeof(level_list));
     63 
     64    l->next = p->levels;
     65    l->where = p->where;
     66    VALGRIND_CREATE_MEMPOOL(l->where, REDZONE_SIZE, 0);
     67    p->levels = l;
     68 }
     69 
     70 void pop(pool *p)
     71 {
     72    level_list *l = p->levels;
     73    p->levels = l->next;
     74    VALGRIND_DESTROY_MEMPOOL(l->where);
     75    (void) VALGRIND_MAKE_MEM_NOACCESS(l->where, p->where-l->where);
     76    p->where = l->where;
     77    if(USE_MMAP)
     78       munmap(l, sizeof(level_list));
     79    else
     80       free(l);
     81 }
     82 
     83 void destroy_pool(pool *p)
     84 {
     85    level_list *l = p->levels;
     86 
     87    while(l) {
     88       pop(p);
     89    }
     90    if(USE_MMAP) {
     91       munmap(p->mem, SUPERBLOCK_SIZE);
     92       munmap(p, sizeof(pool));
     93    } else {
     94       free(p->mem);
     95       free(p);
     96    }
     97 }
     98 
     99 char *allocate(pool *p, int size)
    100 {
    101    char *where;
    102    p->left -= size + (REDZONE_SIZE*2);
    103    where = p->where + REDZONE_SIZE;
    104    p->where += size + (REDZONE_SIZE*2);
    105    VALGRIND_MEMPOOL_ALLOC(p->levels->where, where, size);
    106    return where;
    107 }
    108 
    109 //-------------------------------------------------------------------------
    110 // Rest
    111 //-------------------------------------------------------------------------
    112 
    113 void test(void)
    114 {
    115    char *x1, *x2, *x3, *x4, *x5;
    116 
    117    pool *p = make_pool();
    118 
    119    push(p);
    120 
    121    x1 = allocate(p, 10);
    122    x2 = allocate(p, 20);
    123    push(p);
    124    x3 = allocate(p, 10);
    125    x4 = allocate(p, 20);
    126 
    127    *x1 = 'a';  // valid
    128    *x2 = 'b';  // valid
    129 
    130    x1[-1] = 'h'; // invalid
    131    x1[10] = 'i'; // invalid
    132 
    133    pop(p);
    134 
    135    *x3 = 'c';  // invalid
    136    *x4 = 'd';  // invalid
    137 
    138    *x1 = 'e';  // valid
    139    *x2 = 'f';  // valid
    140 
    141    x5 = allocate(p, 10);
    142 
    143    *x5 = 'g';  // valid
    144 
    145    // pop(p);
    146 
    147    // *x5 = 'g';  // invalid
    148 
    149    // destroy_pool(p);
    150 }
    151 
    152 int main(void)
    153 {
    154    test();
    155    return 0;
    156 }
    157