14a49301eSmrg/**************************************************************************
24a49301eSmrg *
34a49301eSmrg * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
44a49301eSmrg *
54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
64a49301eSmrg * copy of this software and associated documentation files (the "Software"),
74a49301eSmrg * to deal in the Software without restriction, including without limitation
84a49301eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
94a49301eSmrg * and/or sell copies of the Software, and to permit persons to whom the
104a49301eSmrg * Software is furnished to do so, subject to the following conditions:
114a49301eSmrg *
124a49301eSmrg * The above copyright notice and this permission notice shall be included
134a49301eSmrg * in all copies or substantial portions of the Software.
144a49301eSmrg *
154a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
164a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
174a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
224a49301eSmrg *
234a49301eSmrg **************************************************************************/
244a49301eSmrg
254a49301eSmrg
264a49301eSmrg/**
274a49301eSmrg * \file exemem.c
284a49301eSmrg * Functions for allocating executable memory.
294a49301eSmrg *
304a49301eSmrg * \author Keith Whitwell
314a49301eSmrg */
324a49301eSmrg
334a49301eSmrg
344a49301eSmrg#include "pipe/p_compiler.h"
354a49301eSmrg#include "util/u_debug.h"
36cdc920a0Smrg#include "os/os_thread.h"
374a49301eSmrg#include "util/u_memory.h"
384a49301eSmrg
394a49301eSmrg#include "rtasm_execmem.h"
404a49301eSmrg
41af69d88dSmrg#ifndef MAP_ANONYMOUS
424a49301eSmrg#define MAP_ANONYMOUS MAP_ANON
434a49301eSmrg#endif
444a49301eSmrg
454a49301eSmrg#if defined(PIPE_OS_WINDOWS)
464a49301eSmrg#ifndef WIN32_LEAN_AND_MEAN
474a49301eSmrg#define WIN32_LEAN_AND_MEAN 1
484a49301eSmrg#endif
494a49301eSmrg#include <windows.h>
504a49301eSmrg#endif
514a49301eSmrg
5201e04c3fSmrg#if defined(PIPE_OS_UNIX)
534a49301eSmrg
544a49301eSmrg
554a49301eSmrg/*
564a49301eSmrg * Allocate a large block of memory which can hold code then dole it out
574a49301eSmrg * in pieces by means of the generic memory manager code.
584a49301eSmrg */
594a49301eSmrg
604a49301eSmrg#include <unistd.h>
614a49301eSmrg#include <sys/mman.h>
624a49301eSmrg#include "util/u_mm.h"
634a49301eSmrg
644a49301eSmrg#define EXEC_HEAP_SIZE (10*1024*1024)
654a49301eSmrg
6601e04c3fSmrgstatic mtx_t exec_mutex = _MTX_INITIALIZER_NP;
674a49301eSmrg
684a49301eSmrgstatic struct mem_block *exec_heap = NULL;
694a49301eSmrgstatic unsigned char *exec_mem = NULL;
704a49301eSmrg
714a49301eSmrg
72af69d88dSmrgstatic int
734a49301eSmrginit_heap(void)
744a49301eSmrg{
754a49301eSmrg   if (!exec_heap)
764a49301eSmrg      exec_heap = u_mmInit( 0, EXEC_HEAP_SIZE );
774a49301eSmrg
784a49301eSmrg   if (!exec_mem)
794a49301eSmrg      exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE,
804a49301eSmrg					PROT_EXEC | PROT_READ | PROT_WRITE,
814a49301eSmrg					MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
82af69d88dSmrg
83af69d88dSmrg   return (exec_mem != MAP_FAILED);
844a49301eSmrg}
854a49301eSmrg
864a49301eSmrg
874a49301eSmrgvoid *
884a49301eSmrgrtasm_exec_malloc(size_t size)
894a49301eSmrg{
904a49301eSmrg   struct mem_block *block = NULL;
914a49301eSmrg   void *addr = NULL;
924a49301eSmrg
9301e04c3fSmrg   mtx_lock(&exec_mutex);
944a49301eSmrg
95af69d88dSmrg   if (!init_heap())
96af69d88dSmrg      goto bail;
974a49301eSmrg
984a49301eSmrg   if (exec_heap) {
994a49301eSmrg      size = (size + 31) & ~31;  /* next multiple of 32 bytes */
1004a49301eSmrg      block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */
1014a49301eSmrg   }
1024a49301eSmrg
1034a49301eSmrg   if (block)
1044a49301eSmrg      addr = exec_mem + block->ofs;
1054a49301eSmrg   else
1064a49301eSmrg      debug_printf("rtasm_exec_malloc failed\n");
107af69d88dSmrg
108af69d88dSmrgbail:
10901e04c3fSmrg   mtx_unlock(&exec_mutex);
1104a49301eSmrg
1114a49301eSmrg   return addr;
1124a49301eSmrg}
1134a49301eSmrg
1144a49301eSmrg
1154a49301eSmrgvoid
1164a49301eSmrgrtasm_exec_free(void *addr)
1174a49301eSmrg{
11801e04c3fSmrg   mtx_lock(&exec_mutex);
1194a49301eSmrg
1204a49301eSmrg   if (exec_heap) {
1214a49301eSmrg      struct mem_block *block = u_mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
1224a49301eSmrg
1234a49301eSmrg      if (block)
1244a49301eSmrg	 u_mmFreeMem(block);
1254a49301eSmrg   }
1264a49301eSmrg
12701e04c3fSmrg   mtx_unlock(&exec_mutex);
1284a49301eSmrg}
1294a49301eSmrg
1304a49301eSmrg
1314a49301eSmrg#elif defined(PIPE_OS_WINDOWS)
1324a49301eSmrg
1334a49301eSmrg
1344a49301eSmrg/*
1354a49301eSmrg * Avoid Data Execution Prevention.
1364a49301eSmrg */
1374a49301eSmrg
1384a49301eSmrgvoid *
1394a49301eSmrgrtasm_exec_malloc(size_t size)
1404a49301eSmrg{
1414a49301eSmrg   return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1424a49301eSmrg}
1434a49301eSmrg
1444a49301eSmrg
1454a49301eSmrgvoid
1464a49301eSmrgrtasm_exec_free(void *addr)
1474a49301eSmrg{
1484a49301eSmrg   VirtualFree(addr, 0, MEM_RELEASE);
1494a49301eSmrg}
1504a49301eSmrg
1514a49301eSmrg
1524a49301eSmrg#else
1534a49301eSmrg
1544a49301eSmrg
1554a49301eSmrg/*
1564a49301eSmrg * Just use regular memory.
1574a49301eSmrg */
1584a49301eSmrg
1594a49301eSmrgvoid *
1604a49301eSmrgrtasm_exec_malloc(size_t size)
1614a49301eSmrg{
1624a49301eSmrg   return MALLOC( size );
1634a49301eSmrg}
1644a49301eSmrg
1654a49301eSmrg
1664a49301eSmrgvoid
1674a49301eSmrgrtasm_exec_free(void *addr)
1684a49301eSmrg{
1694a49301eSmrg   FREE(addr);
1704a49301eSmrg}
1714a49301eSmrg
1724a49301eSmrg
1734a49301eSmrg#endif
174