1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
13bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci **************************************************************************/
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci/**
27bf215546Sopenharmony_ci * \file exemem.c
28bf215546Sopenharmony_ci * Functions for allocating executable memory.
29bf215546Sopenharmony_ci *
30bf215546Sopenharmony_ci * \author Keith Whitwell
31bf215546Sopenharmony_ci */
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "pipe/p_compiler.h"
35bf215546Sopenharmony_ci#include "util/u_debug.h"
36bf215546Sopenharmony_ci#include "os/os_thread.h"
37bf215546Sopenharmony_ci#include "util/u_memory.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "rtasm_execmem.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#ifndef MAP_ANONYMOUS
42bf215546Sopenharmony_ci#define MAP_ANONYMOUS MAP_ANON
43bf215546Sopenharmony_ci#endif
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#if defined(PIPE_OS_WINDOWS)
46bf215546Sopenharmony_ci#ifndef WIN32_LEAN_AND_MEAN
47bf215546Sopenharmony_ci#define WIN32_LEAN_AND_MEAN 1
48bf215546Sopenharmony_ci#endif
49bf215546Sopenharmony_ci#include <windows.h>
50bf215546Sopenharmony_ci#endif
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci#if defined(PIPE_OS_UNIX)
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci/*
56bf215546Sopenharmony_ci * Allocate a large block of memory which can hold code then dole it out
57bf215546Sopenharmony_ci * in pieces by means of the generic memory manager code.
58bf215546Sopenharmony_ci */
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci#include <unistd.h>
61bf215546Sopenharmony_ci#include <sys/mman.h>
62bf215546Sopenharmony_ci#include "util/u_mm.h"
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci#define EXEC_HEAP_SIZE (10*1024*1024)
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistatic mtx_t exec_mutex = _MTX_INITIALIZER_NP;
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_cistatic struct mem_block *exec_heap = NULL;
69bf215546Sopenharmony_cistatic unsigned char *exec_mem = NULL;
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_cistatic int
73bf215546Sopenharmony_ciinit_heap(void)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   if (!exec_heap)
76bf215546Sopenharmony_ci      exec_heap = u_mmInit( 0, EXEC_HEAP_SIZE );
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   if (!exec_mem)
79bf215546Sopenharmony_ci      exec_mem = (unsigned char *) mmap(NULL, EXEC_HEAP_SIZE,
80bf215546Sopenharmony_ci					PROT_EXEC | PROT_READ | PROT_WRITE,
81bf215546Sopenharmony_ci					MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   return (exec_mem != MAP_FAILED);
84bf215546Sopenharmony_ci}
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_civoid *
88bf215546Sopenharmony_cirtasm_exec_malloc(size_t size)
89bf215546Sopenharmony_ci{
90bf215546Sopenharmony_ci   struct mem_block *block = NULL;
91bf215546Sopenharmony_ci   void *addr = NULL;
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   mtx_lock(&exec_mutex);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (!init_heap())
96bf215546Sopenharmony_ci      goto bail;
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   if (exec_heap) {
99bf215546Sopenharmony_ci      size = (size + 31) & ~31;  /* next multiple of 32 bytes */
100bf215546Sopenharmony_ci      block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */
101bf215546Sopenharmony_ci   }
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   if (block)
104bf215546Sopenharmony_ci      addr = exec_mem + block->ofs;
105bf215546Sopenharmony_ci   else
106bf215546Sopenharmony_ci      debug_printf("rtasm_exec_malloc failed\n");
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_cibail:
109bf215546Sopenharmony_ci   mtx_unlock(&exec_mutex);
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   return addr;
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_civoid
116bf215546Sopenharmony_cirtasm_exec_free(void *addr)
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci   mtx_lock(&exec_mutex);
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   if (exec_heap) {
121bf215546Sopenharmony_ci      struct mem_block *block = u_mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci      if (block)
124bf215546Sopenharmony_ci	 u_mmFreeMem(block);
125bf215546Sopenharmony_ci   }
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   mtx_unlock(&exec_mutex);
128bf215546Sopenharmony_ci}
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci#elif defined(PIPE_OS_WINDOWS)
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci/*
135bf215546Sopenharmony_ci * Avoid Data Execution Prevention.
136bf215546Sopenharmony_ci */
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_civoid *
139bf215546Sopenharmony_cirtasm_exec_malloc(size_t size)
140bf215546Sopenharmony_ci{
141bf215546Sopenharmony_ci   return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
142bf215546Sopenharmony_ci}
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_civoid
146bf215546Sopenharmony_cirtasm_exec_free(void *addr)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   VirtualFree(addr, 0, MEM_RELEASE);
149bf215546Sopenharmony_ci}
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci#else
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci/*
156bf215546Sopenharmony_ci * Just use regular memory.
157bf215546Sopenharmony_ci */
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_civoid *
160bf215546Sopenharmony_cirtasm_exec_malloc(size_t size)
161bf215546Sopenharmony_ci{
162bf215546Sopenharmony_ci   return MALLOC( size );
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_civoid
167bf215546Sopenharmony_cirtasm_exec_free(void *addr)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci   FREE(addr);
170bf215546Sopenharmony_ci}
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci#endif
174