glapi: exec_malloc for dispatch stubs
authorGeorge Sapountzis <gsapountzis@gmail.com>
Thu, 11 Mar 2010 16:04:03 +0000 (18:04 +0200)
committerGeorge Sapountzis <gsapountzis@gmail.com>
Sun, 14 Mar 2010 20:24:27 +0000 (22:24 +0200)
src/mesa/SConscript
src/mesa/glapi/glapi_entrypoint.c
src/mesa/glapi/glapi_execmem.c [new file with mode: 0644]
src/mesa/glapi/glapi_getproc.c
src/mesa/glapi/glapi_priv.h
src/mesa/sources.mak

index e80ec5ee8807d22caeaad12cd377c03abd3572f5..86da6f58bd8e7e53b5971f878e0e6929285c7599 100644 (file)
@@ -250,6 +250,7 @@ if env['platform'] != 'winddk':
                'glapi/glapi.c',
                'glapi/glapi_dispatch.c',
                'glapi/glapi_entrypoint.c',
+               'glapi/glapi_execmem.c',
                'glapi/glapi_getproc.c',
                'glapi/glapi_nop.c',
                'glapi/glthread.c',
index 3256867b1679bf7ba80c988984ad3a578d230b6c..c4f43f66a188854d81f234a6b5b086f52c660851 100644 (file)
@@ -105,7 +105,7 @@ generate_entrypoint(GLuint functionOffset)
     */
    const GLubyte * const template_func = gl_dispatch_functions_start 
      + (DISPATCH_FUNCTION_SIZE * 32);
-   GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE);
+   GLubyte * const code = (GLubyte *) _glapi_exec_malloc(DISPATCH_FUNCTION_SIZE);
 
 
    if ( code != NULL ) {
@@ -288,7 +288,7 @@ generate_entrypoint(GLuint functionOffset)
    extern unsigned int __glapi_sparc_pthread_stub;
    unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub;
 #endif
-   unsigned int *code = (unsigned int *) malloc(sizeof(template));
+   unsigned int *code = (unsigned int *) _glapi_exec_malloc(sizeof(template));
    if (code) {
       code[0] = template[0] | (functionOffset & 0x3fffff);
       code[1] = template[1];
diff --git a/src/mesa/glapi/glapi_execmem.c b/src/mesa/glapi/glapi_execmem.c
new file mode 100644 (file)
index 0000000..6a1fac5
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file glapi_execmem.c
+ *
+ * Function for allocating executable memory for dispatch stubs.
+ *
+ * Copied from main/execmem.c and simplified for dispatch stubs.
+ */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#include "glapi/mesa.h"
+#else
+#include "main/compiler.h"
+#endif
+
+#include "glapi/glthread.h"
+
+
+#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun)
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+#ifdef MESA_SELINUX
+#include <selinux/selinux.h>
+#endif
+
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+
+#define EXEC_MAP_SIZE (4*1024)
+
+_glthread_DECLARE_STATIC_MUTEX(exec_mutex);
+
+static unsigned int head = 0;
+
+static unsigned char *exec_mem = NULL;
+
+
+/*
+ * Dispatch stubs are of fixed size and never freed. Thus, we do not need to
+ * overlay a heap, we just mmap a page and manage through an index.
+ */
+
+static int
+init_map(void)
+{
+#ifdef MESA_SELINUX
+   if (is_selinux_enabled()) {
+      if (!security_get_boolean_active("allow_execmem") ||
+         !security_get_boolean_pending("allow_execmem"))
+         return 0;
+   }
+#endif
+
+   if (!exec_mem)
+      exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+   return (exec_mem != MAP_FAILED);
+}
+
+
+void *
+_glapi_exec_malloc(unsigned int size)
+{
+   void *addr = NULL;
+
+   _glthread_LOCK_MUTEX(exec_mutex);
+
+   if (!init_map())
+      goto bail;
+
+   /* free space check, assumes no integer overflow */
+   if (head + size > EXEC_MAP_SIZE)
+      goto bail;
+
+   /* allocation, assumes proper addr and size alignement */
+   addr = exec_mem + head;
+   head += size;
+
+bail:
+   _glthread_UNLOCK_MUTEX(exec_mutex);
+
+   return addr;
+}
+
+
+#else
+
+void *
+_glapi_exec_malloc(unsigned int size)
+{
+   return malloc(size);
+}
+
+
+#endif
index 295657875dcda712de94c0ffac36b14ce5b8800d..c73e8dd3b040a7ddfbce7ef59400ee3824b3d9c1 100644 (file)
@@ -200,12 +200,6 @@ struct _glapi_function {
 };
 
 
-/*
- * Number of extension functions which we can dynamically add at runtime.
- */
-#define MAX_EXTENSION_FUNCS 300
-
-
 static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
 static GLuint NumExtEntryPoints = 0;
 
index a8516f71a31df94fb6fb4437c1b4965e036f5e1d..0e2de460f2e8c5532b1000c37ef1c44338bef82b 100644 (file)
@@ -28,6 +28,9 @@
 
 #include "glthread.h"
 
+
+/* getproc */
+
 extern void
 _glapi_check_table_not_null(const struct _glapi_table *table);
 
@@ -36,6 +39,14 @@ extern void
 _glapi_check_table(const struct _glapi_table *table);
 
 
+/* execmem */
+
+extern void *
+_glapi_exec_malloc(GLuint size);
+
+
+/* entrypoint */
+
 extern void
 init_glapi_relocs_once(void);
 
@@ -52,6 +63,9 @@ extern _glapi_proc
 get_entrypoint_address(GLuint functionOffset);
 
 
+/**
+ * Size (in bytes) of dispatch function (entrypoint).
+ */
 #if defined(USE_X86_ASM)
 # if defined(GLX_USE_TLS)
 #  define DISPATCH_FUNCTION_SIZE  16
@@ -69,4 +83,15 @@ get_entrypoint_address(GLuint functionOffset);
 #endif
 
 
+/**
+ * Number of extension functions which we can dynamically add at runtime.
+ *
+ * Number of extension functions is also subject to the size of backing exec
+ * mem we allocate. For the common case of dispatch stubs with size 16 bytes,
+ * the two limits will be hit simultaneously. For larger dispatch function
+ * sizes, MAX_EXTENSION_FUNCS is effectively reduced.
+ */
+#define MAX_EXTENSION_FUNCS 256
+
+
 #endif
index 74885548e5a2abfd8b5539919621c2506241beaf..d59e24de1f2fbe5f806d0e2087fd39068981a322 100644 (file)
@@ -89,6 +89,7 @@ GLAPI_SOURCES = \
        glapi/glapi.c \
        glapi/glapi_dispatch.c \
        glapi/glapi_entrypoint.c \
+       glapi/glapi_execmem.c \
        glapi/glapi_getproc.c \
        glapi/glapi_nop.c \
        glapi/glthread.c