Remove C/C++11 header files that we don't really use
[satcheck.git] / mymemory.cc
1 /*      Copyright (c) 2015 Regents of the University of California
2  *
3  *      Author: Brian Demsky <bdemsky@uci.edu>
4  *
5  *      This program is free software; you can redistribute it and/or
6  *      modify it under the terms of the GNU General Public License
7  *      version 2 as published by the Free Software Foundation.
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <dlfcn.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <new>
16
17 #include "mymemory.h"
18 #include "snapshot.h"
19 #include "common.h"
20 #include "threads-model.h"
21 #include "model.h"
22 #include "mcexecution.h"
23
24 #define REQUESTS_BEFORE_ALLOC 1024
25
26 size_t allocatedReqs[REQUESTS_BEFORE_ALLOC] = { 0 };
27 int nextRequest = 0;
28 int howManyFreed = 0;
29 int switch_alloc = 0;
30 #if !USE_MPROTECT_SNAPSHOT
31 static mspace sStaticSpace = NULL;
32 #endif
33
34 /** Non-snapshotting calloc for our use. */
35 void *model_calloc(size_t count, size_t size)
36 {
37 #if USE_MPROTECT_SNAPSHOT
38         static void *(*callocp)(size_t count, size_t size) = NULL;
39         char *error;
40         void *ptr;
41
42         /* get address of libc malloc */
43         if (!callocp) {
44                 callocp = (void * (*)(size_t, size_t))dlsym(RTLD_NEXT, "calloc");
45                 if ((error = dlerror()) != NULL) {
46                         fputs(error, stderr);
47                         exit(EXIT_FAILURE);
48                 }
49         }
50         ptr = callocp(count, size);
51         return ptr;
52 #else
53         if (!sStaticSpace)
54                 sStaticSpace = create_shared_mspace();
55         return mspace_calloc(sStaticSpace, count, size);
56 #endif
57 }
58
59 /** Non-snapshotting malloc for our use. */
60 void *model_malloc(size_t size)
61 {
62 #if USE_MPROTECT_SNAPSHOT
63         static void *(*mallocp)(size_t size) = NULL;
64         char *error;
65         void *ptr;
66
67         /* get address of libc malloc */
68         if (!mallocp) {
69                 mallocp = (void * (*)(size_t))dlsym(RTLD_NEXT, "malloc");
70                 if ((error = dlerror()) != NULL) {
71                         fputs(error, stderr);
72                         exit(EXIT_FAILURE);
73                 }
74         }
75         ptr = mallocp(size);
76         return ptr;
77 #else
78         if (!sStaticSpace)
79                 sStaticSpace = create_shared_mspace();
80         return mspace_malloc(sStaticSpace, size);
81 #endif
82 }
83
84 /** @brief Snapshotting realloc, for use by model-checker (not user progs) */
85 void *model_realloc(void *ptr, size_t size)
86 {
87 #if USE_MPROTECT_SNAPSHOT
88         static void *(*reallocp)(void *ptr, size_t size) = NULL;
89         char *error;
90         void *tmpptr;
91
92         /* get address of libc malloc */
93         if (!reallocp) {
94                 reallocp = (void * (*)(void *,size_t))dlsym(RTLD_NEXT, "realloc");
95                 if ((error = dlerror()) != NULL) {
96                         fputs(error, stderr);
97                         exit(EXIT_FAILURE);
98                 }
99         }
100         tmpptr = reallocp(ptr, size);
101         return tmpptr;
102 #else
103         if (!sStaticSpace)
104                 sStaticSpace = create_shared_mspace();
105         return mspace_realloc(sStaticSpace, ptr, size);
106 #endif
107 }
108
109 /** @brief Snapshotting malloc, for use by model-checker (not user progs) */
110 void * snapshot_malloc(size_t size)
111 {
112         void *tmp = mspace_malloc(model_snapshot_space, size);
113         ASSERT(tmp);
114         return tmp;
115 }
116
117 /** @brief Snapshotting calloc, for use by model-checker (not user progs) */
118 void * snapshot_calloc(size_t count, size_t size)
119 {
120         void *tmp = mspace_calloc(model_snapshot_space, count, size);
121         ASSERT(tmp);
122         return tmp;
123 }
124
125 /** @brief Snapshotting realloc, for use by model-checker (not user progs) */
126 void *snapshot_realloc(void *ptr, size_t size)
127 {
128         void *tmp = mspace_realloc(model_snapshot_space, ptr, size);
129         ASSERT(tmp);
130         return tmp;
131 }
132
133 /** @brief Snapshotting free, for use by model-checker (not user progs) */
134 void snapshot_free(void *ptr)
135 {
136         mspace_free(model_snapshot_space, ptr);
137 }
138
139 /** Non-snapshotting free for our use. */
140 void model_free(void *ptr)
141 {
142 #if USE_MPROTECT_SNAPSHOT
143         static void (*freep)(void *);
144         char *error;
145
146         /* get address of libc free */
147         if (!freep) {
148                 freep = (void (*)(void *))dlsym(RTLD_NEXT, "free");
149                 if ((error = dlerror()) != NULL) {
150                         fputs(error, stderr);
151                         exit(EXIT_FAILURE);
152                 }
153         }
154         freep(ptr);
155 #else
156         mspace_free(sStaticSpace, ptr);
157 #endif
158 }
159
160 /** Bootstrap allocation. Problem is that the dynamic linker calls require
161  *  calloc to work and calloc requires the dynamic linker to work. */
162
163 #define BOOTSTRAPBYTES 131072
164 char bootstrapmemory[BOOTSTRAPBYTES];
165 size_t offset = 0;
166
167 void * HandleEarlyAllocationRequest(size_t sz)
168 {
169         /* Align to 8 byte boundary */
170         sz = (sz + 7) & ~7;
171
172         if (sz > (BOOTSTRAPBYTES-offset)) {
173                 model_print("OUT OF BOOTSTRAP MEMORY.  Increase the size of BOOTSTRAPBYTES in mymemory.cc\n");
174                 exit(EXIT_FAILURE);
175         }
176
177         void *pointer = (void *)&bootstrapmemory[offset];
178         offset += sz;
179         return pointer;
180 }
181
182 /** @brief Global mspace reference for the model-checker's snapshotting heap */
183 mspace model_snapshot_space = NULL;
184
185 #if USE_MPROTECT_SNAPSHOT
186
187 /** @brief Global mspace reference for the user's snapshotting heap */
188 void * user_snapshot_space = NULL;
189 mspace thread_snapshot_space = NULL;
190
191 struct snapshot_heap_data * snapshot_struct;
192
193 /** Check whether this is bootstrapped memory that we should not free */
194 static bool DontFree(void *ptr)
195 {
196         return (ptr >= (&bootstrapmemory[0]) && ptr < (&bootstrapmemory[BOOTSTRAPBYTES]));
197 }
198
199
200 static void * user_malloc(size_t size) {
201         return model->get_execution()->alloc(size);
202 }
203
204 /**
205  * @brief The allocator function for "user" allocation
206  *
207  * Should only be used for allocations which will not disturb the allocation
208  * patterns of a user thread.
209  */
210 void * real_user_malloc(size_t size)
211 {
212         size=(size+7)&~((size_t)7);
213         void *tmp = snapshot_struct->allocation_ptr;
214         snapshot_struct->allocation_ptr = (void *)((char *) snapshot_struct->allocation_ptr +size);
215
216         ASSERT(snapshot_struct->allocation_ptr <= snapshot_struct->top_ptr);
217         return tmp;
218 }
219
220 /**
221  * @brief Snapshotting malloc implementation for user programs
222  *
223  * Do NOT call this function from a model-checker context. Doing so may disrupt
224  * the allocation patterns of a user thread.
225  */
226 void *malloc(size_t size)
227 {
228         if (user_snapshot_space) {
229                 /* Only perform user allocations from user context */
230                 if (switch_alloc) {
231                         return model_malloc(size);
232                 } else {
233                         return user_malloc(size);
234                 }
235         } else
236                 return HandleEarlyAllocationRequest(size);
237 }
238
239 /** @brief Snapshotting free implementation for user programs */
240 void free(void * ptr)
241 {
242         if (!DontFree(ptr))
243                 if (switch_alloc) {
244                         model_free(ptr);
245                 } else {
246                         mspace_free(user_snapshot_space, ptr);
247                 }
248 }
249
250 /** @brief Snapshotting realloc implementation for user programs */
251 void *realloc(void *ptr, size_t size)
252 {
253         ASSERT(false);
254         return NULL;
255 }
256
257 /** @brief Snapshotting calloc implementation for user programs */
258 void * calloc(size_t num, size_t size)
259 {
260         if (user_snapshot_space) {
261                 void *tmp = user_malloc(num * size);
262                 bzero(tmp, num*size);
263                 ASSERT(tmp);
264                 return tmp;
265         } else {
266                 void *tmp = HandleEarlyAllocationRequest(size * num);
267                 memset(tmp, 0, size * num);
268                 return tmp;
269         }
270 }
271
272 /** @brief Snapshotting allocation function for use by the Thread class only */
273 void * Thread_malloc(size_t size)
274 {
275         void *tmp = mspace_malloc(thread_snapshot_space, size);
276         ASSERT(tmp);
277         return tmp;
278 }
279
280 /** @brief Snapshotting free function for use by the Thread class only */
281 void Thread_free(void *ptr)
282 {
283         free(ptr);
284 }
285
286 /** @brief Snapshotting new operator for user programs */
287 void * operator new(size_t size) throw(std::bad_alloc)
288 {
289         return malloc(size);
290 }
291
292 /** @brief Snapshotting delete operator for user programs */
293 void operator delete(void *p) throw()
294 {
295         free(p);
296 }
297
298 /** @brief Snapshotting new[] operator for user programs */
299 void * operator new[](size_t size) throw(std::bad_alloc)
300 {
301         return malloc(size);
302 }
303
304 /** @brief Snapshotting delete[] operator for user programs */
305 void operator delete[](void *p, size_t size)
306 {
307         free(p);
308 }
309
310 #else   /* !USE_MPROTECT_SNAPSHOT */
311
312 /** @brief Snapshotting allocation function for use by the Thread class only */
313 void * Thread_malloc(size_t size)
314 {
315         return malloc(size);
316 }
317
318 /** @brief Snapshotting free function for use by the Thread class only */
319 void Thread_free(void *ptr)
320 {
321         free(ptr);
322 }
323
324 #endif/* !USE_MPROTECT_SNAPSHOT */