model: remove snapshotted 'nextThread'
[c11tester.git] / mymemory.cc
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <dlfcn.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <new>
7
8 #include "mymemory.h"
9 #include "snapshot.h"
10 #include "snapshotimp.h"
11 #include "common.h"
12
13 #define REQUESTS_BEFORE_ALLOC 1024
14
15 size_t allocatedReqs[ REQUESTS_BEFORE_ALLOC ] = { 0 };
16 int nextRequest = 0;
17 int howManyFreed = 0;
18 #if !USE_MPROTECT_SNAPSHOT
19 static mspace sStaticSpace = NULL;
20 #endif
21
22 /** Non-snapshotting calloc for our use. */
23 void *model_calloc(size_t count, size_t size)
24 {
25 #if USE_MPROTECT_SNAPSHOT
26         static void *(*callocp)(size_t count, size_t size) = NULL;
27         char *error;
28         void *ptr;
29
30         /* get address of libc malloc */
31         if (!callocp) {
32                 callocp = (void * (*)(size_t, size_t))dlsym(RTLD_NEXT, "calloc");
33                 if ((error = dlerror()) != NULL) {
34                         fputs(error, stderr);
35                         exit(EXIT_FAILURE);
36                 }
37         }
38         ptr = callocp(count, size);
39         return ptr;
40 #else
41         if (!snapshotrecord) {
42                 createSharedMemory();
43         }
44         if (NULL == sStaticSpace)
45                 sStaticSpace = create_mspace_with_base(( void *)( snapshotrecord->mSharedMemoryBase), SHARED_MEMORY_DEFAULT -sizeof(struct SnapShot), 1);
46         return mspace_calloc(sStaticSpace, count, size);
47 #endif
48 }
49
50 /** Non-snapshotting malloc for our use. */
51 void *model_malloc(size_t size)
52 {
53 #if USE_MPROTECT_SNAPSHOT
54         static void *(*mallocp)(size_t size) = NULL;
55         char *error;
56         void *ptr;
57
58         /* get address of libc malloc */
59         if (!mallocp) {
60                 mallocp = (void * (*)(size_t))dlsym(RTLD_NEXT, "malloc");
61                 if ((error = dlerror()) != NULL) {
62                         fputs(error, stderr);
63                         exit(EXIT_FAILURE);
64                 }
65         }
66         ptr = mallocp(size);
67         return ptr;
68 #else
69         if (!snapshotrecord) {
70                 createSharedMemory();
71         }
72         if (NULL == sStaticSpace)
73                 sStaticSpace = create_mspace_with_base(( void *)( snapshotrecord->mSharedMemoryBase), SHARED_MEMORY_DEFAULT -sizeof(struct SnapShot), 1);
74         return mspace_malloc(sStaticSpace, size);
75 #endif
76 }
77
78 /** @brief Snapshotting malloc, for use by model-checker (not user progs) */
79 void * snapshot_malloc(size_t size)
80 {
81         void *tmp = mspace_malloc(model_snapshot_space, size);
82         ASSERT(tmp);
83         return tmp;
84 }
85
86 /** @brief Snapshotting calloc, for use by model-checker (not user progs) */
87 void * snapshot_calloc(size_t count, size_t size)
88 {
89         void *tmp = mspace_calloc(model_snapshot_space, count, size);
90         ASSERT(tmp);
91         return tmp;
92 }
93
94 /** @brief Snapshotting realloc, for use by model-checker (not user progs) */
95 void *snapshot_realloc(void *ptr, size_t size)
96 {
97         void *tmp = mspace_realloc(model_snapshot_space, ptr, size);
98         ASSERT(tmp);
99         return tmp;
100 }
101
102 /** @brief Snapshotting free, for use by model-checker (not user progs) */
103 void snapshot_free(void *ptr)
104 {
105         mspace_free(model_snapshot_space, ptr);
106 }
107
108 /** Non-snapshotting free for our use. */
109 void model_free(void *ptr)
110 {
111 #if USE_MPROTECT_SNAPSHOT
112         static void (*freep)(void *);
113         char *error;
114
115         /* get address of libc free */
116         if (!freep) {
117                 freep = ( void  ( * )( void *))dlsym(RTLD_NEXT, "free");
118                 if ((error = dlerror()) != NULL) {
119                         fputs(error, stderr);
120                         exit(EXIT_FAILURE);
121                 }
122         }
123         freep(ptr);
124 #else
125         mspace_free(sStaticSpace, ptr);
126 #endif
127 }
128
129 /** Bootstrap allocation.  Problem is that the dynamic linker calls
130  *  require calloc to work and calloc requires the dynamic linker to
131  *      work.  */
132
133 #define BOOTSTRAPBYTES 4096
134 char bootstrapmemory[BOOTSTRAPBYTES];
135 size_t offset = 0;
136
137 void * HandleEarlyAllocationRequest(size_t sz)
138 {
139         /* Align to 8 byte boundary */
140         sz = (sz + 7) & ~7;
141
142         if (sz > (BOOTSTRAPBYTES-offset)) {
143                 model_print("OUT OF BOOTSTRAP MEMORY\n");
144                 exit(EXIT_FAILURE);
145         }
146
147         void *pointer= (void *)&bootstrapmemory[offset];
148         offset += sz;
149         return pointer;
150 }
151
152 /** @brief Global mspace reference for the model-checker's snapshotting heap */
153 mspace model_snapshot_space = NULL;
154
155 #if USE_MPROTECT_SNAPSHOT
156
157 /** @brief Global mspace reference for the user's snapshotting heap */
158 mspace user_snapshot_space = NULL;
159
160 /** Check whether this is bootstrapped memory that we should not free */
161 static bool DontFree(void *ptr)
162 {
163         return (ptr >= (&bootstrapmemory[0]) && ptr < (&bootstrapmemory[BOOTSTRAPBYTES]));
164 }
165
166 /** @brief Snapshotting malloc implementation for user programs */
167 void *malloc(size_t size)
168 {
169         if (user_snapshot_space) {
170                 void *tmp = mspace_malloc(user_snapshot_space, size);
171                 ASSERT(tmp);
172                 return tmp;
173         } else
174                 return HandleEarlyAllocationRequest(size);
175 }
176
177 /** @brief Snapshotting free implementation for user programs */
178 void free(void * ptr)
179 {
180         if (!DontFree(ptr))
181                 mspace_free(user_snapshot_space, ptr);
182 }
183
184 /** @brief Snapshotting realloc implementation for user programs */
185 void *realloc(void *ptr, size_t size)
186 {
187         void *tmp = mspace_realloc(user_snapshot_space, ptr, size);
188         ASSERT(tmp);
189         return tmp;
190 }
191
192 /** @brief Snapshotting calloc implementation for user programs */
193 void * calloc(size_t num, size_t size)
194 {
195         if (user_snapshot_space) {
196                 void *tmp = mspace_calloc(user_snapshot_space, num, size);
197                 ASSERT(tmp);
198                 return tmp;
199         } else {
200                 void *tmp = HandleEarlyAllocationRequest(size * num);
201                 memset(tmp, 0, size * num);
202                 return tmp;
203         }
204 }
205
206 /** @brief Snapshotting new operator for user programs */
207 void * operator new(size_t size) throw(std::bad_alloc)
208 {
209         return malloc(size);
210 }
211
212 /** @brief Snapshotting delete operator for user programs */
213 void operator delete(void *p) throw()
214 {
215         free(p);
216 }
217
218 /** @brief Snapshotting new[] operator for user programs */
219 void * operator new[](size_t size) throw(std::bad_alloc)
220 {
221         return malloc(size);
222 }
223
224 /** @brief Snapshotting delete[] operator for user programs */
225 void operator delete[](void *p, size_t size)
226 {
227         free(p);
228 }
229 #endif /* USE_MPROTECT_SNAPSHOT */