1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
4848b8605Smrg *
5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg * copy of this software and associated documentation files (the "Software"),
7848b8605Smrg * to deal in the Software without restriction, including without limitation
8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
10848b8605Smrg * Software is furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice shall be included
13848b8605Smrg * in all copies or substantial portions of the Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
22848b8605Smrg *
23848b8605Smrg **************************************************************************/
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file exemem.c
28848b8605Smrg * Functions for allocating executable memory.
29848b8605Smrg *
30848b8605Smrg * \author Keith Whitwell
31848b8605Smrg */
32848b8605Smrg
33848b8605Smrg
34848b8605Smrg#include "pipe/p_compiler.h"
35848b8605Smrg#include "util/u_debug.h"
36848b8605Smrg#include "os/os_thread.h"
37848b8605Smrg#include "util/u_memory.h"
38848b8605Smrg
39848b8605Smrg#include "rtasm_execmem.h"
40848b8605Smrg
41848b8605Smrg#ifndef MAP_ANONYMOUS
42848b8605Smrg#define MAP_ANONYMOUS MAP_ANON
43848b8605Smrg#endif
44848b8605Smrg
45848b8605Smrg#if defined(PIPE_OS_WINDOWS)
46848b8605Smrg#ifndef WIN32_LEAN_AND_MEAN
47848b8605Smrg#define WIN32_LEAN_AND_MEAN 1
48848b8605Smrg#endif
49848b8605Smrg#include <windows.h>
50848b8605Smrg#endif
51848b8605Smrg
52b8e80941Smrg#if defined(PIPE_OS_UNIX)
53848b8605Smrg
54848b8605Smrg
55848b8605Smrg/*
56848b8605Smrg * Allocate a large block of memory which can hold code then dole it out
57848b8605Smrg * in pieces by means of the generic memory manager code.
58848b8605Smrg */
59848b8605Smrg
60848b8605Smrg#include <unistd.h>
61848b8605Smrg#include <sys/mman.h>
62848b8605Smrg#include "util/u_mm.h"
63848b8605Smrg
64848b8605Smrg#define EXEC_HEAP_SIZE (10*1024*1024)
65848b8605Smrg
66b8e80941Smrgstatic mtx_t exec_mutex = _MTX_INITIALIZER_NP;
67848b8605Smrg
68848b8605Smrgstatic struct mem_block *exec_heap = NULL;
69848b8605Smrgstatic unsigned char *exec_mem = NULL;
70848b8605Smrg
71848b8605Smrg
72848b8605Smrgstatic int
73848b8605Smrginit_heap(void)
74848b8605Smrg{
75848b8605Smrg   if (!exec_heap)
76848b8605Smrg      exec_heap = u_mmInit( 0, EXEC_HEAP_SIZE );
77848b8605Smrg
78848b8605Smrg   if (!exec_mem)
79848b8605Smrg      exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE,
80848b8605Smrg					PROT_EXEC | PROT_READ | PROT_WRITE,
81848b8605Smrg					MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
82848b8605Smrg
83848b8605Smrg   return (exec_mem != MAP_FAILED);
84848b8605Smrg}
85848b8605Smrg
86848b8605Smrg
87848b8605Smrgvoid *
88848b8605Smrgrtasm_exec_malloc(size_t size)
89848b8605Smrg{
90848b8605Smrg   struct mem_block *block = NULL;
91848b8605Smrg   void *addr = NULL;
92848b8605Smrg
93b8e80941Smrg   mtx_lock(&exec_mutex);
94848b8605Smrg
95848b8605Smrg   if (!init_heap())
96848b8605Smrg      goto bail;
97848b8605Smrg
98848b8605Smrg   if (exec_heap) {
99848b8605Smrg      size = (size + 31) & ~31;  /* next multiple of 32 bytes */
100848b8605Smrg      block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */
101848b8605Smrg   }
102848b8605Smrg
103848b8605Smrg   if (block)
104848b8605Smrg      addr = exec_mem + block->ofs;
105848b8605Smrg   else
106848b8605Smrg      debug_printf("rtasm_exec_malloc failed\n");
107848b8605Smrg
108848b8605Smrgbail:
109b8e80941Smrg   mtx_unlock(&exec_mutex);
110848b8605Smrg
111848b8605Smrg   return addr;
112848b8605Smrg}
113848b8605Smrg
114848b8605Smrg
115848b8605Smrgvoid
116848b8605Smrgrtasm_exec_free(void *addr)
117848b8605Smrg{
118b8e80941Smrg   mtx_lock(&exec_mutex);
119848b8605Smrg
120848b8605Smrg   if (exec_heap) {
121848b8605Smrg      struct mem_block *block = u_mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
122848b8605Smrg
123848b8605Smrg      if (block)
124848b8605Smrg	 u_mmFreeMem(block);
125848b8605Smrg   }
126848b8605Smrg
127b8e80941Smrg   mtx_unlock(&exec_mutex);
128848b8605Smrg}
129848b8605Smrg
130848b8605Smrg
131848b8605Smrg#elif defined(PIPE_OS_WINDOWS)
132848b8605Smrg
133848b8605Smrg
134848b8605Smrg/*
135848b8605Smrg * Avoid Data Execution Prevention.
136848b8605Smrg */
137848b8605Smrg
138848b8605Smrgvoid *
139848b8605Smrgrtasm_exec_malloc(size_t size)
140848b8605Smrg{
141848b8605Smrg   return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
142848b8605Smrg}
143848b8605Smrg
144848b8605Smrg
145848b8605Smrgvoid
146848b8605Smrgrtasm_exec_free(void *addr)
147848b8605Smrg{
148848b8605Smrg   VirtualFree(addr, 0, MEM_RELEASE);
149848b8605Smrg}
150848b8605Smrg
151848b8605Smrg
152848b8605Smrg#else
153848b8605Smrg
154848b8605Smrg
155848b8605Smrg/*
156848b8605Smrg * Just use regular memory.
157848b8605Smrg */
158848b8605Smrg
159848b8605Smrgvoid *
160848b8605Smrgrtasm_exec_malloc(size_t size)
161848b8605Smrg{
162848b8605Smrg   return MALLOC( size );
163848b8605Smrg}
164848b8605Smrg
165848b8605Smrg
166848b8605Smrgvoid
167848b8605Smrgrtasm_exec_free(void *addr)
168848b8605Smrg{
169848b8605Smrg   FREE(addr);
170848b8605Smrg}
171848b8605Smrg
172848b8605Smrg
173848b8605Smrg#endif
174