#include <unistd.h>
#include "tests/sys_mman.h"
#include <assert.h>
#include <stdlib.h>
#include "../memcheck.h"
#define SUPERBLOCK_SIZE 100000
#define REDZONE_SIZE 8
static const int USE_MMAP = 0;
typedef struct _level_list
{
struct _level_list *next;
char *where;
// Padding ensures the struct is the same size on 32-bit and 64-bit
// machines.
char padding[16 - 2*sizeof(char*)];
} level_list;
typedef struct _pool {
char *mem;
char *where;
level_list *levels;
int size, left;
// Padding ensures the struct is the same size on 32-bit and 64-bit
// machines.
char padding[24 - 3*sizeof(char*)];
} pool;
pool *make_pool()
{
pool *p;
if(USE_MMAP) {
p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
} else {
p = (pool *)malloc(sizeof(pool));
p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE);
}
p->size = p->left = SUPERBLOCK_SIZE;
p->levels = NULL;
(void) VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE);
return p;
}
void push(pool *p)
{
level_list *l;
if(USE_MMAP)
l = (level_list *)mmap(0, sizeof(level_list),
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
else
l = (level_list *)malloc(sizeof(level_list));
l->next = p->levels;
l->where = p->where;
VALGRIND_CREATE_MEMPOOL(l->where, REDZONE_SIZE, 0);
p->levels = l;
}
void pop(pool *p)
{
level_list *l = p->levels;
p->levels = l->next;
VALGRIND_DESTROY_MEMPOOL(l->where);
(void) VALGRIND_MAKE_MEM_NOACCESS(l->where, p->where-l->where);
p->where = l->where;
if(USE_MMAP)
munmap(l, sizeof(level_list));
else
free(l);
}
void destroy_pool(pool *p)
{
level_list *l = p->levels;
while(l) {
pop(p);
}
if(USE_MMAP) {
munmap(p->mem, SUPERBLOCK_SIZE);
munmap(p, sizeof(pool));
} else {
free(p->mem);
free(p);
}
}
char *allocate(pool *p, int size)
{
char *where;
p->left -= size + (REDZONE_SIZE*2);
where = p->where + REDZONE_SIZE;
p->where += size + (REDZONE_SIZE*2);
VALGRIND_MEMPOOL_ALLOC(p->levels->where, where, size);
return where;
}
//-------------------------------------------------------------------------
// Rest
//-------------------------------------------------------------------------
void test(void)
{
char *x1, *x2, *x3, *x4, *x5;
pool *p = make_pool();
push(p);
x1 = allocate(p, 10);
x2 = allocate(p, 20);
push(p);
x3 = allocate(p, 10);
x4 = allocate(p, 20);
*x1 = 'a'; // valid
*x2 = 'b'; // valid
x1[-1] = 'h'; // invalid
x1[10] = 'i'; // invalid
pop(p);
*x3 = 'c'; // invalid
*x4 = 'd'; // invalid
*x1 = 'e'; // valid
*x2 = 'f'; // valid
x5 = allocate(p, 10);
*x5 = 'g'; // valid
// pop(p);
// *x5 = 'g'; // invalid
// destroy_pool(p);
}
int main(void)
{
test();
return 0;
}