Annotation of embedaddon/pcre/sljit/sljitUtils.c, revision 1.1.1.4
1.1 misho 1: /*
2: * Stack-less Just-In-Time compiler
3: *
1.1.1.2 misho 4: * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
1.1 misho 5: *
6: * Redistribution and use in source and binary forms, with or without modification, are
7: * permitted provided that the following conditions are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright notice, this list of
10: * conditions and the following disclaimer.
11: *
12: * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13: * of conditions and the following disclaimer in the documentation and/or other materials
14: * provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19: * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: /* ------------------------------------------------------------------------ */
28: /* Locks */
29: /* ------------------------------------------------------------------------ */
30:
31: #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
32:
1.1.1.3 misho 33: #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
34:
35: #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
36:
37: static SLJIT_INLINE void allocator_grab_lock(void)
38: {
39: /* Always successful. */
40: }
41:
42: static SLJIT_INLINE void allocator_release_lock(void)
43: {
44: /* Always successful. */
45: }
46:
47: #endif /* SLJIT_EXECUTABLE_ALLOCATOR */
48:
49: #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
50:
51: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
52: {
53: /* Always successful. */
54: }
55:
56: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
57: {
58: /* Always successful. */
59: }
60:
61: #endif /* SLJIT_UTIL_GLOBAL_LOCK */
62:
63: #elif defined(_WIN32) /* SLJIT_SINGLE_THREADED */
1.1 misho 64:
65: #include "windows.h"
66:
67: #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
68:
69: static HANDLE allocator_mutex = 0;
70:
71: static SLJIT_INLINE void allocator_grab_lock(void)
72: {
73: /* No idea what to do if an error occures. Static mutexes should never fail... */
74: if (!allocator_mutex)
75: allocator_mutex = CreateMutex(NULL, TRUE, NULL);
76: else
77: WaitForSingleObject(allocator_mutex, INFINITE);
78: }
79:
80: static SLJIT_INLINE void allocator_release_lock(void)
81: {
82: ReleaseMutex(allocator_mutex);
83: }
84:
85: #endif /* SLJIT_EXECUTABLE_ALLOCATOR */
86:
87: #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
88:
89: static HANDLE global_mutex = 0;
90:
91: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
92: {
93: /* No idea what to do if an error occures. Static mutexes should never fail... */
94: if (!global_mutex)
95: global_mutex = CreateMutex(NULL, TRUE, NULL);
96: else
97: WaitForSingleObject(global_mutex, INFINITE);
98: }
99:
100: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
101: {
102: ReleaseMutex(global_mutex);
103: }
104:
105: #endif /* SLJIT_UTIL_GLOBAL_LOCK */
106:
107: #else /* _WIN32 */
108:
109: #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
110:
1.1.1.4 ! misho 111: #include <pthread.h>
! 112:
1.1 misho 113: static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
114:
115: static SLJIT_INLINE void allocator_grab_lock(void)
116: {
117: pthread_mutex_lock(&allocator_mutex);
118: }
119:
120: static SLJIT_INLINE void allocator_release_lock(void)
121: {
122: pthread_mutex_unlock(&allocator_mutex);
123: }
124:
125: #endif /* SLJIT_EXECUTABLE_ALLOCATOR */
126:
127: #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
128:
1.1.1.4 ! misho 129: #include <pthread.h>
! 130:
1.1 misho 131: static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
132:
133: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
134: {
135: pthread_mutex_lock(&global_mutex);
136: }
137:
138: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
139: {
140: pthread_mutex_unlock(&global_mutex);
141: }
142:
143: #endif /* SLJIT_UTIL_GLOBAL_LOCK */
144:
145: #endif /* _WIN32 */
146:
147: /* ------------------------------------------------------------------------ */
148: /* Stack */
149: /* ------------------------------------------------------------------------ */
150:
1.1.1.4 ! misho 151: #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
1.1 misho 152:
153: #ifdef _WIN32
154: #include "windows.h"
155: #else
1.1.1.4 ! misho 156: /* Provides mmap function. */
1.1 misho 157: #include <sys/mman.h>
1.1.1.4 ! misho 158: /* For detecting the page size. */
1.1 misho 159: #include <unistd.h>
1.1.1.4 ! misho 160:
! 161: #ifndef MAP_ANON
! 162:
! 163: #include <fcntl.h>
! 164:
! 165: /* Some old systems does not have MAP_ANON. */
! 166: static sljit_si dev_zero = -1;
! 167:
! 168: #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
! 169:
! 170: static SLJIT_INLINE sljit_si open_dev_zero(void)
! 171: {
! 172: dev_zero = open("/dev/zero", O_RDWR);
! 173: return dev_zero < 0;
! 174: }
! 175:
! 176: #else /* SLJIT_SINGLE_THREADED */
! 177:
! 178: #include <pthread.h>
! 179:
! 180: static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
! 181:
! 182: static SLJIT_INLINE sljit_si open_dev_zero(void)
! 183: {
! 184: pthread_mutex_lock(&dev_zero_mutex);
! 185: dev_zero = open("/dev/zero", O_RDWR);
! 186: pthread_mutex_unlock(&dev_zero_mutex);
! 187: return dev_zero < 0;
! 188: }
! 189:
! 190: #endif /* SLJIT_SINGLE_THREADED */
! 191:
1.1 misho 192: #endif
193:
1.1.1.4 ! misho 194: #endif
! 195:
! 196: #endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
! 197:
! 198: #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
! 199:
1.1 misho 200: /* Planning to make it even more clever in the future. */
1.1.1.4 ! misho 201: static sljit_sw sljit_page_align = 0;
1.1 misho 202:
203: SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit)
204: {
205: struct sljit_stack *stack;
206: union {
207: void *ptr;
208: sljit_uw uw;
209: } base;
210: #ifdef _WIN32
211: SYSTEM_INFO si;
212: #endif
213:
214: if (limit > max_limit || limit < 1)
215: return NULL;
216:
217: #ifdef _WIN32
218: if (!sljit_page_align) {
219: GetSystemInfo(&si);
220: sljit_page_align = si.dwPageSize - 1;
221: }
222: #else
223: if (!sljit_page_align) {
224: sljit_page_align = sysconf(_SC_PAGESIZE);
225: /* Should never happen. */
226: if (sljit_page_align < 0)
227: sljit_page_align = 4096;
228: sljit_page_align--;
229: }
230: #endif
231:
232: /* Align limit and max_limit. */
233: max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
234:
235: stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack));
236: if (!stack)
237: return NULL;
238:
239: #ifdef _WIN32
1.1.1.4 ! misho 240: base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
1.1 misho 241: if (!base.ptr) {
242: SLJIT_FREE(stack);
243: return NULL;
244: }
245: stack->base = base.uw;
246: stack->limit = stack->base;
247: stack->max_limit = stack->base + max_limit;
248: if (sljit_stack_resize(stack, stack->base + limit)) {
249: sljit_free_stack(stack);
250: return NULL;
251: }
252: #else
1.1.1.4 ! misho 253: #ifdef MAP_ANON
! 254: base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
! 255: #else
! 256: if (dev_zero < 0) {
! 257: if (open_dev_zero()) {
! 258: SLJIT_FREE(stack);
! 259: return NULL;
! 260: }
! 261: }
! 262: base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
! 263: #endif
1.1 misho 264: if (base.ptr == MAP_FAILED) {
265: SLJIT_FREE(stack);
266: return NULL;
267: }
268: stack->base = base.uw;
269: stack->limit = stack->base + limit;
270: stack->max_limit = stack->base + max_limit;
271: #endif
272: stack->top = stack->base;
273: return stack;
274: }
275:
276: #undef PAGE_ALIGN
277:
278: SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack)
279: {
280: #ifdef _WIN32
281: VirtualFree((void*)stack->base, 0, MEM_RELEASE);
282: #else
283: munmap((void*)stack->base, stack->max_limit - stack->base);
284: #endif
285: SLJIT_FREE(stack);
286: }
287:
1.1.1.4 ! misho 288: SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
1.1 misho 289: {
290: sljit_uw aligned_old_limit;
291: sljit_uw aligned_new_limit;
292:
293: if ((new_limit > stack->max_limit) || (new_limit < stack->base))
294: return -1;
295: #ifdef _WIN32
296: aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
297: aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
298: if (aligned_new_limit != aligned_old_limit) {
299: if (aligned_new_limit > aligned_old_limit) {
300: if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE))
301: return -1;
302: }
303: else {
304: if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
305: return -1;
306: }
307: }
308: stack->limit = new_limit;
309: return 0;
310: #else
311: if (new_limit >= stack->limit) {
312: stack->limit = new_limit;
313: return 0;
314: }
315: aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
316: aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
1.1.1.4 ! misho 317: /* If madvise is available, we release the unnecessary space. */
! 318: #if defined(MADV_DONTNEED)
! 319: if (aligned_new_limit < aligned_old_limit)
! 320: madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
! 321: #elif defined(POSIX_MADV_DONTNEED)
1.1 misho 322: if (aligned_new_limit < aligned_old_limit)
1.1.1.3 misho 323: posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
1.1.1.4 ! misho 324: #endif
1.1 misho 325: stack->limit = new_limit;
326: return 0;
327: #endif
328: }
329:
330: #endif /* SLJIT_UTIL_STACK */
331:
332: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>