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