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