File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pcre / sljit / sljitUtils.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:25:57 2013 UTC (11 years ago) by misho
Branches: pcre, MAIN
CVS tags: v8_34, v8_33, HEAD
8.33

    1: /*
    2:  *    Stack-less Just-In-Time compiler
    3:  *
    4:  *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
    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: 
   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 */
   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: 
  111: #include <pthread.h>
  112: 
  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: 
  129: #include <pthread.h>
  130: 
  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: 
  151: #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
  152: 
  153: #ifdef _WIN32
  154: #include "windows.h"
  155: #else
  156: /* Provides mmap function. */
  157: #include <sys/mman.h>
  158: /* For detecting the page size. */
  159: #include <unistd.h>
  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: 
  192: #endif
  193: 
  194: #endif
  195: 
  196: #endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
  197: 
  198: #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
  199: 
  200: /* Planning to make it even more clever in the future. */
  201: static sljit_sw sljit_page_align = 0;
  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
  240: 	base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
  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
  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
  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: 
  288: SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
  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;
  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)
  322: 	if (aligned_new_limit < aligned_old_limit)
  323: 		posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
  324: #endif
  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>