Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 /**
     27  * \file execmem.c
     28  * Functions for allocating executable memory.
     29  *
     30  * \author Keith Whitwell
     31  */
     32 
     33 
     34 #include <stdio.h>
     35 #include "imports.h"
     36 
     37 
     38 
     39 #if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun) || defined(__HAIKU__)
     40 
     41 /*
     42  * Allocate a large block of memory which can hold code then dole it out
     43  * in pieces by means of the generic memory manager code.
     44 */
     45 
     46 #include <unistd.h>
     47 #include <sys/mman.h>
     48 #include "mm.h"
     49 
     50 #ifdef MESA_SELINUX
     51 #include <selinux/selinux.h>
     52 #endif
     53 
     54 
     55 #ifndef MAP_ANONYMOUS
     56 #define MAP_ANONYMOUS MAP_ANON
     57 #endif
     58 
     59 
     60 #define EXEC_HEAP_SIZE (10*1024*1024)
     61 
     62 static mtx_t exec_mutex = _MTX_INITIALIZER_NP;
     63 
     64 static struct mem_block *exec_heap = NULL;
     65 static unsigned char *exec_mem = NULL;
     66 
     67 
     68 static int
     69 init_heap(void)
     70 {
     71 #ifdef MESA_SELINUX
     72    if (is_selinux_enabled()) {
     73       if (!security_get_boolean_active("allow_execmem") ||
     74 	  !security_get_boolean_pending("allow_execmem"))
     75          return 0;
     76    }
     77 #endif
     78 
     79    if (!exec_heap)
     80       exec_heap = mmInit( 0, EXEC_HEAP_SIZE );
     81 
     82    if (!exec_mem)
     83       exec_mem = mmap(NULL, EXEC_HEAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE,
     84 		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     85 
     86    return (exec_mem != MAP_FAILED);
     87 }
     88 
     89 
     90 void *
     91 _mesa_exec_malloc(GLuint size)
     92 {
     93    struct mem_block *block = NULL;
     94    void *addr = NULL;
     95 
     96    mtx_lock(&exec_mutex);
     97 
     98    if (!init_heap())
     99       goto bail;
    100 
    101    if (exec_heap) {
    102       size = (size + 31) & ~31;
    103       block = mmAllocMem( exec_heap, size, 32, 0 );
    104    }
    105 
    106    if (block)
    107       addr = exec_mem + block->ofs;
    108    else
    109       printf("_mesa_exec_malloc failed\n");
    110 
    111 bail:
    112    mtx_unlock(&exec_mutex);
    113 
    114    return addr;
    115 }
    116 
    117 
    118 void
    119 _mesa_exec_free(void *addr)
    120 {
    121    mtx_lock(&exec_mutex);
    122 
    123    if (exec_heap) {
    124       struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
    125 
    126       if (block)
    127 	 mmFreeMem(block);
    128    }
    129 
    130    mtx_unlock(&exec_mutex);
    131 }
    132 
    133 
    134 #else
    135 
    136 /*
    137  * Just use regular memory.
    138  */
    139 
    140 void *
    141 _mesa_exec_malloc(GLuint size)
    142 {
    143    return malloc( size );
    144 }
    145 
    146 
    147 void
    148 _mesa_exec_free(void *addr)
    149 {
    150    free(addr);
    151 }
    152 
    153 
    154 #endif
    155