summaryrefslogtreecommitdiff
path: root/src/mesa/glapi
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/glapi')
-rw-r--r--src/mesa/glapi/glapi_entrypoint.c165
-rw-r--r--src/mesa/glapi/glapi_execmem.c127
-rw-r--r--src/mesa/glapi/glapi_getproc.c6
-rw-r--r--src/mesa/glapi/glapi_priv.h39
4 files changed, 255 insertions, 82 deletions
diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c
index 5e6e5995f2..c4f43f66a1 100644
--- a/src/mesa/glapi/glapi_entrypoint.c
+++ b/src/mesa/glapi/glapi_entrypoint.c
@@ -65,7 +65,7 @@ get_entrypoint_address(GLuint functionOffset)
#endif
-#if defined(PTHREADS) || defined(GLX_USE_TLS)
+#if defined(USE_X86_ASM)
/**
* Perform platform-specific GL API entry-point fixups.
@@ -73,7 +73,7 @@ get_entrypoint_address(GLuint functionOffset)
static void
init_glapi_relocs( void )
{
-#if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT)
+#if defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT)
extern unsigned long _x86_get_dispatch(void);
char run_time_patch[] = {
0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */
@@ -88,8 +88,63 @@ init_glapi_relocs( void )
curr_func += DISPATCH_FUNCTION_SIZE;
}
#endif
-#ifdef USE_SPARC_ASM
- extern void __glapi_sparc_icache_flush(unsigned int *);
+}
+
+
+/**
+ * Generate a dispatch function (entrypoint) which jumps through
+ * the given slot number (offset) in the current dispatch table.
+ * We need assembly language in order to accomplish this.
+ */
+_glapi_proc
+generate_entrypoint(GLuint functionOffset)
+{
+ /* 32 is chosen as something of a magic offset. For x86, the dispatch
+ * at offset 32 is the first one where the offset in the
+ * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
+ */
+ const GLubyte * const template_func = gl_dispatch_functions_start
+ + (DISPATCH_FUNCTION_SIZE * 32);
+ GLubyte * const code = (GLubyte *) _glapi_exec_malloc(DISPATCH_FUNCTION_SIZE);
+
+
+ if ( code != NULL ) {
+ (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
+ fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
+ }
+
+ return (_glapi_proc) code;
+}
+
+
+/**
+ * This function inserts a new dispatch offset into the assembly language
+ * stub that was generated with the preceeding function.
+ */
+void
+fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
+{
+ GLubyte * const code = (GLubyte *) entrypoint;
+
+#if defined(GLX_USE_TLS)
+ *((unsigned int *)(code + 8)) = 4 * offset;
+#elif defined(THREADS)
+ *((unsigned int *)(code + 11)) = 4 * offset;
+ *((unsigned int *)(code + 22)) = 4 * offset;
+#else
+ *((unsigned int *)(code + 7)) = 4 * offset;
+#endif
+}
+
+
+#elif defined(USE_SPARC_ASM)
+
+extern void __glapi_sparc_icache_flush(unsigned int *);
+
+static void
+init_glapi_relocs( void )
+{
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
static const unsigned int template[] = {
#ifdef GLX_USE_TLS
0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */
@@ -155,7 +210,7 @@ init_glapi_relocs( void )
int idx;
#endif
-#if defined(GLX_USE_TLS)
+#ifdef GLX_USE_TLS
code[0] = template[0] | (dispatch >> 10);
code[1] = template[1];
__glapi_sparc_icache_flush(&code[0]);
@@ -215,51 +270,10 @@ init_glapi_relocs( void )
#endif
}
-void
-init_glapi_relocs_once( void )
-{
- static pthread_once_t once_control = PTHREAD_ONCE_INIT;
- pthread_once( & once_control, init_glapi_relocs );
-}
-
-#else
-
-void
-init_glapi_relocs_once( void ) { }
-
-#endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */
-
-
-#ifdef USE_SPARC_ASM
-extern void __glapi_sparc_icache_flush(unsigned int *);
-#endif
-/**
- * Generate a dispatch function (entrypoint) which jumps through
- * the given slot number (offset) in the current dispatch table.
- * We need assembly language in order to accomplish this.
- */
_glapi_proc
generate_entrypoint(GLuint functionOffset)
{
-#if defined(USE_X86_ASM)
- /* 32 is chosen as something of a magic offset. For x86, the dispatch
- * at offset 32 is the first one where the offset in the
- * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
- */
- const GLubyte * const template_func = gl_dispatch_functions_start
- + (DISPATCH_FUNCTION_SIZE * 32);
- GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE);
-
-
- if ( code != NULL ) {
- (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
- fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
- }
-
- return (_glapi_proc) code;
-#elif defined(USE_SPARC_ASM)
-
#if defined(PTHREADS) || defined(GLX_USE_TLS)
static const unsigned int template[] = {
0x07000000, /* sethi %hi(0), %g3 */
@@ -274,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];
@@ -287,45 +301,52 @@ generate_entrypoint(GLuint functionOffset)
}
return (_glapi_proc) code;
#endif
-
-#else
- (void) functionOffset;
- return NULL;
-#endif /* USE_*_ASM */
}
-/**
- * This function inserts a new dispatch offset into the assembly language
- * stub that was generated with the preceeding function.
- */
void
fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
{
-#if defined(USE_X86_ASM)
- GLubyte * const code = (GLubyte *) entrypoint;
-
-#if DISPATCH_FUNCTION_SIZE == 32
- *((unsigned int *)(code + 11)) = 4 * offset;
- *((unsigned int *)(code + 22)) = 4 * offset;
-#elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
- *((unsigned int *)(code + 8)) = 4 * offset;
-#elif DISPATCH_FUNCTION_SIZE == 16
- *((unsigned int *)(code + 7)) = 4 * offset;
-#else
-# error Invalid DISPATCH_FUNCTION_SIZE!
-#endif
-
-#elif defined(USE_SPARC_ASM)
unsigned int *code = (unsigned int *) entrypoint;
+
code[0] &= ~0x3fffff;
code[0] |= (offset * sizeof(void *)) & 0x3fffff;
__glapi_sparc_icache_flush(&code[0]);
-#else
+}
+
+
+#else /* USE_*_ASM */
+static void
+init_glapi_relocs( void )
+{
+}
+
+
+_glapi_proc
+generate_entrypoint(GLuint functionOffset)
+{
+ (void) functionOffset;
+ return NULL;
+}
+
+
+void
+fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
+{
/* an unimplemented architecture */
(void) entrypoint;
(void) offset;
+}
#endif /* USE_*_ASM */
+
+
+void
+init_glapi_relocs_once( void )
+{
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
+ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+ pthread_once( & once_control, init_glapi_relocs );
+#endif
}
diff --git a/src/mesa/glapi/glapi_execmem.c b/src/mesa/glapi/glapi_execmem.c
new file mode 100644
index 0000000000..6a1fac597f
--- /dev/null
+++ b/src/mesa/glapi/glapi_execmem.c
@@ -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
diff --git a/src/mesa/glapi/glapi_getproc.c b/src/mesa/glapi/glapi_getproc.c
index 295657875d..c73e8dd3b0 100644
--- a/src/mesa/glapi/glapi_getproc.c
+++ b/src/mesa/glapi/glapi_getproc.c
@@ -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;
diff --git a/src/mesa/glapi/glapi_priv.h b/src/mesa/glapi/glapi_priv.h
index 7cd81ee8dc..0e2de460f2 100644
--- a/src/mesa/glapi/glapi_priv.h
+++ b/src/mesa/glapi/glapi_priv.h
@@ -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,15 +63,35 @@ extern _glapi_proc
get_entrypoint_address(GLuint functionOffset);
-#if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
-# define DISPATCH_FUNCTION_SIZE 16
-#elif defined(USE_X86_ASM)
-# if defined(THREADS) && !defined(GLX_USE_TLS)
+/**
+ * Size (in bytes) of dispatch function (entrypoint).
+ */
+#if defined(USE_X86_ASM)
+# if defined(GLX_USE_TLS)
+# define DISPATCH_FUNCTION_SIZE 16
+# elif defined(THREADS)
# define DISPATCH_FUNCTION_SIZE 32
# else
# define DISPATCH_FUNCTION_SIZE 16
# endif
#endif
+#if defined(USE_X64_64_ASM)
+# if defined(GLX_USE_TLS)
+# define DISPATCH_FUNCTION_SIZE 16
+# endif
+#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