This source file includes following definitions.
- init_pagesize
- init_mmap_file
- do_init_mmap_file
- gl_once_define
- alloc_pages
- free_pages
- immmalloc
- immfreeze
- immfree
- immmalloc
- immfreeze
- immfree
- immstrdup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #include "immutable.h"
24
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #if IMMUTABLE_EFFECTIVE
30
31
32
33 # include <limits.h>
34
35
36 # include <stdint.h>
37
38 # include <stdio.h>
39
40 # if defined _WIN32 && !defined __CYGWIN__
41
42
43 # define WIN32_LEAN_AND_MEAN
44 # define WIN32_EXTRA_LEAN
45 # include <windows.h>
46
47
48 # undef CreateFileMapping
49 # define CreateFileMapping CreateFileMappingA
50
51 # else
52
53
54 # include <unistd.h>
55
56
57 # ifdef __hpux
58 extern
59 # ifdef __cplusplus
60 "C"
61 # endif
62 int getpagesize (void);
63 # endif
64
65
66 # include <sys/types.h>
67 # include <sys/mman.h>
68
69
70 # include <unistd.h>
71 # include <fcntl.h>
72
73 # include "glthread/lock.h"
74
75 # endif
76
77
78
79
80
81
82 static uintptr_t pagesize;
83
84
85 static void
86 init_pagesize (void)
87 {
88
89 # if defined _WIN32 && !defined __CYGWIN__
90
91
92
93 SYSTEM_INFO info;
94 GetSystemInfo (&info);
95 pagesize = info.dwPageSize;
96 # else
97 pagesize = getpagesize ();
98 # endif
99 }
100
101
102 # if defined _WIN32 && !defined __CYGWIN__
103
104 static inline void
105 init_mmap_file (void)
106 {
107 }
108
109 # else
110
111
112 static int file_fd;
113 static long file_length;
114
115
116 static void
117 do_init_mmap_file (void)
118 {
119 char filename[100];
120 sprintf (filename, "%s/glimmdata-%d-%ld", "/tmp", getpid (), random ());
121 file_fd = open (filename, O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0700);
122 if (file_fd < 0)
123 {
124 fprintf (stderr, "glimm: Cannot open %s!\n", filename);
125 abort ();
126 }
127
128
129 unlink (filename);
130
131 file_length = 0;
132 }
133
134
135 gl_once_define (static, for_mmap_once)
136
137 static inline void
138 init_mmap_file (void)
139 {
140
141
142 gl_once (for_mmap_once, do_init_mmap_file);
143 }
144
145 # endif
146
147
148
149
150 # define SHARED_LINK_HEADER_SIZE \
151 (INTPTR_WIDTH / CHAR_BIT)
152
153
154
155
156 static uintptr_t
157 alloc_pages (size_t size)
158 {
159 # if defined _WIN32 && !defined __CYGWIN__
160
161
162
163 HANDLE h =
164 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT,
165 size >> 16 >> 16, size & 0xFFFFFFFFU, NULL);
166 if (h == NULL)
167 {
168 fprintf (stderr,
169 "glimm: Cannot allocate file mapping. GetLastError() = 0x%08X\n",
170 (unsigned int) GetLastError ());
171 return 0;
172 }
173
174
175 char *mem_w = (char *) MapViewOfFile (h, FILE_MAP_WRITE, 0, 0, size);
176 char *mem_r = (char *) MapViewOfFile (h, FILE_MAP_READ, 0, 0, size);
177 if (mem_w == NULL || mem_r == NULL)
178 {
179
180
181 if (mem_w != NULL)
182 UnmapViewOfFile (mem_w);
183 if (mem_r != NULL)
184 UnmapViewOfFile (mem_r);
185 return 0;
186 }
187
188
189 if (!CloseHandle (h))
190 {
191 UnmapViewOfFile (mem_w);
192 UnmapViewOfFile (mem_r);
193 CloseHandle (h);
194 return 0;
195 }
196 # else
197
198 long new_file_length = file_length + size;
199 if (ftruncate (file_fd, new_file_length) < 0)
200 {
201 fprintf (stderr, "glimm: Cannot extend backing file!\n");
202 return 0;
203 }
204
205 char *mem_w = (char *) mmap (NULL, size, PROT_READ | PROT_WRITE,
206 MAP_SHARED, file_fd, file_length);
207 char *mem_r = (char *) mmap (NULL, size, PROT_READ,
208 MAP_SHARED, file_fd, file_length);
209 if (mem_w == (char *)(-1) || mem_r == (char *)(-1))
210 {
211 if (mem_w != (char *)(-1))
212 munmap (mem_w, size);
213 if (mem_r != (char *)(-1))
214 munmap (mem_r, size);
215 return 0;
216 }
217 file_length = new_file_length;
218 # endif
219
220
221 ((intptr_t *) mem_w)[0] = mem_r - mem_w;
222 return (uintptr_t) mem_w;
223 }
224
225
226
227 static void
228 free_pages (uintptr_t pages, size_t size)
229 {
230 pages -= SHARED_LINK_HEADER_SIZE;
231 if ((pages & (pagesize - 1)) != 0)
232 abort ();
233 char *mem_w = (char *) pages;
234 char *mem_r = mem_w + ((intptr_t *) mem_w)[0];
235 # if defined _WIN32 && !defined __CYGWIN__
236 if (!UnmapViewOfFile (mem_w))
237 abort ();
238 if (!UnmapViewOfFile (mem_r))
239 abort ();
240 # else
241 if (munmap (mem_w, size) < 0)
242 abort ();
243 if (munmap (mem_r, size) < 0)
244 abort ();
245 # endif
246 }
247
248
249 # undef PAGESIZE
250
251
252
253 # define PAGESIZE pagesize
254
255
256 # if defined __CYGWIN__ || (defined __linux__ && defined __powerpc__)
257 # define PAGESIZE_MAX 65536
258 # else
259 # define PAGESIZE_MAX 16384
260 # endif
261
262 # define ALLOC_PAGES alloc_pages
263 # define FREE_PAGES free_pages
264 # define ALIGNMENT sizeof (void *)
265 # define PAGE_RESERVED_HEADER_SIZE SHARED_LINK_HEADER_SIZE
266
267 # include "ssfmalloc.h"
268
269
270 void *
271 immmalloc (size_t size)
272 {
273
274 if (!pagesize)
275 {
276 init_mmap_file ();
277 init_pagesize ();
278 }
279
280 void *writable_pointer = (void *) allocate_block (size);
281 if (writable_pointer == NULL)
282 errno = ENOMEM;
283 return writable_pointer;
284 }
285
286 const void *
287 immfreeze (void *writable_pointer)
288 {
289 uintptr_t mem_w = (uintptr_t) writable_pointer & -(intptr_t)pagesize;
290 return (void *) ((uintptr_t) writable_pointer + ((intptr_t *) mem_w)[0]);
291 }
292
293 void
294 immfree (const void *readonly_pointer)
295 {
296 uintptr_t mem_r = (uintptr_t) readonly_pointer & -(intptr_t)pagesize;
297 free_block ((uintptr_t) readonly_pointer - ((intptr_t *) mem_r)[0]);
298 }
299
300 #else
301
302
303 void *
304 immmalloc (size_t size)
305 {
306 void *p = malloc (size);
307 if (p == NULL)
308 errno = ENOMEM;
309 return p;
310 }
311
312 const void *
313 immfreeze (void *writable_pointer)
314 {
315 return writable_pointer;
316 }
317
318 void
319 immfree (const void *readonly_pointer)
320 {
321 void *writable_pointer = (void *) readonly_pointer;
322 free (writable_pointer);
323 }
324
325 #endif
326
327
328 const char *
329 immstrdup (const char *string)
330 {
331 size_t size = strlen (string) + 1;
332 void *wp = immmalloc (size);
333 if (wp == NULL)
334 return NULL;
335 memcpy (wp, string, size);
336 return (const char *) immfreeze (wp);
337 }