From 6c8e5151f14bc642e3995a42ad0f90f407c04d5c Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Thu, 11 Mar 2010 18:04:02 +0200 Subject: glapi: organize arch-specific code by arch --- src/mesa/glapi/glapi_entrypoint.c | 69 ++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 19 deletions(-) (limited to 'src/mesa/glapi/glapi_entrypoint.c') diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c index 5e6e5995f2..7fffd2986f 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,16 @@ init_glapi_relocs( void ) curr_func += DISPATCH_FUNCTION_SIZE; } #endif -#ifdef USE_SPARC_ASM - extern void __glapi_sparc_icache_flush(unsigned int *); +} + +#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 +163,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,24 +223,25 @@ init_glapi_relocs( void ) #endif } +#else + +static void +init_glapi_relocs( void ) { } + +#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 } -#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 +#if defined(USE_X86_ASM) /** * Generate a dispatch function (entrypoint) which jumps through @@ -242,7 +251,6 @@ extern void __glapi_sparc_icache_flush(unsigned int *); _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. @@ -258,8 +266,13 @@ generate_entrypoint(GLuint functionOffset) } return (_glapi_proc) code; +} + #elif defined(USE_SPARC_ASM) +_glapi_proc +generate_entrypoint(GLuint functionOffset) +{ #if defined(PTHREADS) || defined(GLX_USE_TLS) static const unsigned int template[] = { 0x07000000, /* sethi %hi(0), %g3 */ @@ -287,13 +300,21 @@ generate_entrypoint(GLuint functionOffset) } return (_glapi_proc) code; #endif +} #else + +_glapi_proc +generate_entrypoint(GLuint functionOffset) +{ (void) functionOffset; return NULL; -#endif /* USE_*_ASM */ } +#endif /* USE_*_ASM */ + + +#if defined(USE_X86_ASM) /** * This function inserts a new dispatch offset into the assembly language @@ -302,7 +323,6 @@ generate_entrypoint(GLuint functionOffset) 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 @@ -315,17 +335,28 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) #else # error Invalid DISPATCH_FUNCTION_SIZE! #endif +} #elif defined(USE_SPARC_ASM) + +void +fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +{ unsigned int *code = (unsigned int *) entrypoint; + code[0] &= ~0x3fffff; code[0] |= (offset * sizeof(void *)) & 0x3fffff; __glapi_sparc_icache_flush(&code[0]); +} + #else +void +fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +{ /* an unimplemented architecture */ (void) entrypoint; (void) offset; +} #endif /* USE_*_ASM */ -} -- cgit v1.2.3 From 0ed0114de9f057e928124bada7289a4496a6d35f Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Thu, 11 Mar 2010 18:04:02 +0200 Subject: glapi: organize arch-specific code by arch (2) --- src/mesa/glapi/glapi_entrypoint.c | 154 ++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 81 deletions(-) (limited to 'src/mesa/glapi/glapi_entrypoint.c') diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c index 7fffd2986f..9bc3878354 100644 --- a/src/mesa/glapi/glapi_entrypoint.c +++ b/src/mesa/glapi/glapi_entrypoint.c @@ -90,6 +90,55 @@ init_glapi_relocs( void ) #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) +{ + /* 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; +} + + +/** + * 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 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) extern void __glapi_sparc_icache_flush(unsigned int *); @@ -223,52 +272,6 @@ init_glapi_relocs( void ) #endif } -#else - -static void -init_glapi_relocs( void ) { } - -#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 -} - - -#if defined(USE_X86_ASM) - -/** - * 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 *) 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) _glapi_proc generate_entrypoint(GLuint functionOffset) @@ -302,54 +305,33 @@ generate_entrypoint(GLuint functionOffset) #endif } -#else -_glapi_proc -generate_entrypoint(GLuint functionOffset) +void +fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) { - (void) functionOffset; - return NULL; -} + unsigned int *code = (unsigned int *) entrypoint; -#endif /* USE_*_ASM */ + code[0] &= ~0x3fffff; + code[0] |= (offset * sizeof(void *)) & 0x3fffff; + __glapi_sparc_icache_flush(&code[0]); +} -#if defined(USE_X86_ASM) +#else /* 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) +static void +init_glapi_relocs( void ) { - 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) -void -fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +_glapi_proc +generate_entrypoint(GLuint functionOffset) { - unsigned int *code = (unsigned int *) entrypoint; - - code[0] &= ~0x3fffff; - code[0] |= (offset * sizeof(void *)) & 0x3fffff; - __glapi_sparc_icache_flush(&code[0]); + (void) functionOffset; + return NULL; } -#else void fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) @@ -360,3 +342,13 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint 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 +} -- cgit v1.2.3 From 8fd7ee1815dd5880f94f13d88225d7be6f549ae6 Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Thu, 11 Mar 2010 18:04:03 +0200 Subject: glapi: this one should be by THREAD --- src/mesa/glapi/glapi_entrypoint.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/mesa/glapi/glapi_entrypoint.c') diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c index 9bc3878354..3256867b16 100644 --- a/src/mesa/glapi/glapi_entrypoint.c +++ b/src/mesa/glapi/glapi_entrypoint.c @@ -126,15 +126,13 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) { GLubyte * const code = (GLubyte *) entrypoint; -#if DISPATCH_FUNCTION_SIZE == 32 +#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; -#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! + *((unsigned int *)(code + 7)) = 4 * offset; #endif } -- cgit v1.2.3 From 41eab95b3bc29a4fe6fd08b7f1f80cef5bdc097f Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Thu, 11 Mar 2010 18:04:03 +0200 Subject: glapi: exec_malloc for dispatch stubs --- src/mesa/SConscript | 1 + src/mesa/glapi/glapi_entrypoint.c | 4 +- src/mesa/glapi/glapi_execmem.c | 127 ++++++++++++++++++++++++++++++++++++++ src/mesa/glapi/glapi_getproc.c | 6 -- src/mesa/glapi/glapi_priv.h | 25 ++++++++ src/mesa/sources.mak | 1 + 6 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 src/mesa/glapi/glapi_execmem.c (limited to 'src/mesa/glapi/glapi_entrypoint.c') diff --git a/src/mesa/SConscript b/src/mesa/SConscript index e80ec5ee88..86da6f58bd 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -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', diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c index 3256867b16..c4f43f66a1 100644 --- a/src/mesa/glapi/glapi_entrypoint.c +++ b/src/mesa/glapi/glapi_entrypoint.c @@ -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 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 +#include "glapi/mesa.h" +#else +#include "main/compiler.h" +#endif + +#include "glapi/glthread.h" + + +#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun) + +#include +#include + +#ifdef MESA_SELINUX +#include +#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 a8516f71a3..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,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 diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak index 74885548e5..d59e24de1f 100644 --- a/src/mesa/sources.mak +++ b/src/mesa/sources.mak @@ -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 -- cgit v1.2.3