Add TLS support to libGL and, by virtue of using glthread.h and GL_CALL, all
DRI drivers. A TLS enabled libGL can load a TLS or a non-TLS DRI driver, but a TLS DRI driver requires a TLS enabled libGL. This fixes bug #1822.
This commit is contained in:
@@ -16,6 +16,8 @@ MKDEP = /usr/X11R6/bin/makedepend
|
|||||||
WARN_FLAGS = -Wall
|
WARN_FLAGS = -Wall
|
||||||
OPT_FLAGS = -O -g
|
OPT_FLAGS = -O -g
|
||||||
PIC_FLAGS = -fPIC
|
PIC_FLAGS = -fPIC
|
||||||
|
|
||||||
|
# Add '-DGLX_USE_TLS' to ARCH_FLAGS to enable TLS support.
|
||||||
ARCH_FLAGS ?=
|
ARCH_FLAGS ?=
|
||||||
|
|
||||||
DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
|
DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
|
||||||
|
@@ -222,6 +222,15 @@ static __DRIdriver *OpenDriver(const char *driverName)
|
|||||||
void *handle = NULL;
|
void *handle = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* If TLS support is enabled, try to open the TLS version of the driver
|
||||||
|
* binary first. If that fails, try the non-TLS version.
|
||||||
|
*/
|
||||||
|
#ifdef GLX_USE_TLS
|
||||||
|
snprintf(realDriverName, 200, "%s/tls/%s_dri.so", libDir, driverName);
|
||||||
|
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
|
||||||
|
handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( handle == NULL ) {
|
if ( handle == NULL ) {
|
||||||
snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
|
snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
|
||||||
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
|
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
|
||||||
|
@@ -63,7 +63,10 @@ class PrintGenericStubs(gl_XML.FilterGLAPISpecBase):
|
|||||||
print "* the symbol visibility mode to 'default'."
|
print "* the symbol visibility mode to 'default'."
|
||||||
print '*/'
|
print '*/'
|
||||||
print '#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303'
|
print '#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303'
|
||||||
print '#pragma GCC visibility push(default)'
|
print '# pragma GCC visibility push(default)'
|
||||||
|
print '# define HIDDEN(x) .hidden x'
|
||||||
|
print '#else'
|
||||||
|
print '# define HIDDEN(x)'
|
||||||
print '#endif'
|
print '#endif'
|
||||||
print ''
|
print ''
|
||||||
print '#ifndef __WIN32__'
|
print '#ifndef __WIN32__'
|
||||||
@@ -94,7 +97,17 @@ class PrintGenericStubs(gl_XML.FilterGLAPISpecBase):
|
|||||||
print '# define THREADS'
|
print '# define THREADS'
|
||||||
print '#endif'
|
print '#endif'
|
||||||
print ''
|
print ''
|
||||||
print '#if defined(PTHREADS)'
|
print '#ifdef GLX_USE_TLS'
|
||||||
|
print ''
|
||||||
|
print '# define GL_STUB(fn,off,fn_alt)\t\t\t\\'
|
||||||
|
print 'ALIGNTEXT16;\t\t\t\t\t\t\\'
|
||||||
|
print 'GLOBL_FN(GL_PREFIX(fn, fn_alt));\t\t\t\\'
|
||||||
|
print 'GL_PREFIX(fn, fn_alt):\t\t\t\t\t\\'
|
||||||
|
print '\tCALL(_x86_get_dispatch) ;\t\t\t\\'
|
||||||
|
print '\tNOP ;\t\t\t\t\t\t\\'
|
||||||
|
print '\tJMP(GL_OFFSET(off))'
|
||||||
|
print ''
|
||||||
|
print '#elif defined(PTHREADS)'
|
||||||
print '# define GL_STUB(fn,off,fn_alt)\t\t\t\\'
|
print '# define GL_STUB(fn,off,fn_alt)\t\t\t\\'
|
||||||
print 'ALIGNTEXT16;\t\t\t\t\t\t\\'
|
print 'ALIGNTEXT16;\t\t\t\t\t\t\\'
|
||||||
print 'GLOBL_FN(GL_PREFIX(fn, fn_alt));\t\t\t\\'
|
print 'GLOBL_FN(GL_PREFIX(fn, fn_alt));\t\t\t\\'
|
||||||
@@ -136,7 +149,16 @@ class PrintGenericStubs(gl_XML.FilterGLAPISpecBase):
|
|||||||
print ''
|
print ''
|
||||||
print 'SEG_TEXT'
|
print 'SEG_TEXT'
|
||||||
print ''
|
print ''
|
||||||
print '#ifdef PTHREADS'
|
print '#ifdef GLX_USE_TLS'
|
||||||
|
print ''
|
||||||
|
print '\tGLOBL\tGLNAME(_x86_get_dispatch)'
|
||||||
|
print '\tHIDDEN(GLNAME(_x86_get_dispatch))'
|
||||||
|
print 'ALIGNTEXT16'
|
||||||
|
print 'GLNAME(_x86_get_dispatch):'
|
||||||
|
print '\tmovl\t%gs:_glapi_tls_Dispatch@NTPOFF, %eax'
|
||||||
|
print '\tret'
|
||||||
|
print ''
|
||||||
|
print '#elif defined(PTHREADS)'
|
||||||
print 'EXTERN GLNAME(_glapi_Dispatch)'
|
print 'EXTERN GLNAME(_glapi_Dispatch)'
|
||||||
print 'EXTERN GLNAME(_gl_DispatchTSD)'
|
print 'EXTERN GLNAME(_gl_DispatchTSD)'
|
||||||
print 'EXTERN GLNAME(pthread_getspecific)'
|
print 'EXTERN GLNAME(pthread_getspecific)'
|
||||||
@@ -152,12 +174,38 @@ class PrintGenericStubs(gl_XML.FilterGLAPISpecBase):
|
|||||||
print 'EXTERN GLNAME(_glapi_get_dispatch)'
|
print 'EXTERN GLNAME(_glapi_get_dispatch)'
|
||||||
print '#endif'
|
print '#endif'
|
||||||
print ''
|
print ''
|
||||||
print '\t\tALIGNTEXT16 ; GLOBL GLNAME(gl_dispatch_functions_start)'
|
|
||||||
|
print '#if defined( GLX_USE_TLS )'
|
||||||
|
print '\t\t.section\twtext, "awx", @progbits'
|
||||||
|
print '#endif /* defined( GLX_USE_TLS ) */'
|
||||||
|
|
||||||
|
print ''
|
||||||
|
print '\t\tALIGNTEXT16'
|
||||||
|
print '\t\tGLOBL GLNAME(gl_dispatch_functions_start)'
|
||||||
|
print '\t\tHIDDEN(GLNAME(gl_dispatch_functions_start))'
|
||||||
print 'GLNAME(gl_dispatch_functions_start):'
|
print 'GLNAME(gl_dispatch_functions_start):'
|
||||||
print ''
|
print ''
|
||||||
return
|
return
|
||||||
|
|
||||||
def printRealFooter(self):
|
def printRealFooter(self):
|
||||||
|
print ''
|
||||||
|
print '\t\tGLOBL\tGLNAME(gl_dispatch_functions_end)'
|
||||||
|
print '\t\tHIDDEN(GLNAME(gl_dispatch_functions_end))'
|
||||||
|
print '\t\tALIGNTEXT16'
|
||||||
|
print 'GLNAME(gl_dispatch_functions_end):'
|
||||||
|
print ''
|
||||||
|
print '#if defined(GLX_USE_TLS) && defined(__linux__)'
|
||||||
|
print ' .section ".note.ABI-tag", "a"'
|
||||||
|
print ' .p2align 2'
|
||||||
|
print ' .long 1f - 0f /* name length */'
|
||||||
|
print ' .long 3f - 2f /* data length */'
|
||||||
|
print ' .long 1 /* note length */'
|
||||||
|
print '0: .asciz "GNU" /* vendor name */'
|
||||||
|
print '1: .p2align 2'
|
||||||
|
print '2: .long 0 /* note data: the ABI tag */'
|
||||||
|
print ' .long 2,4,20 /* Minimum kernel version w/TLS */'
|
||||||
|
print '3: .p2align 2 /* pad out section */'
|
||||||
|
print '#endif /* GLX_USE_TLS */'
|
||||||
print ''
|
print ''
|
||||||
print '#endif /* __WIN32__ */'
|
print '#endif /* __WIN32__ */'
|
||||||
return
|
return
|
||||||
@@ -167,11 +215,11 @@ class PrintGenericStubs(gl_XML.FilterGLAPISpecBase):
|
|||||||
|
|
||||||
alt = "%s@%u" % (f.name, stack)
|
alt = "%s@%u" % (f.name, stack)
|
||||||
if f.fn_alias == None:
|
if f.fn_alias == None:
|
||||||
print '\tGL_STUB(%s, _gloffset_%s, %s)' % (f.name, f.real_name, alt)
|
print '\tGL_STUB(%s, _gloffset_%s, %s)' % (f.name, f.real_name, alt)
|
||||||
else:
|
else:
|
||||||
alias_alt = "%s@%u" % (f.real_name, stack)
|
alias_alt = "%s@%u" % (f.real_name, stack)
|
||||||
print '\tGL_STUB_ALIAS(%s, _gloffset_%s, %s, %s, %s)' % \
|
print '\tGL_STUB_ALIAS(%s, _gloffset_%s, %s, %s, %s)' % \
|
||||||
(f.name, f.real_name, alt, f.real_name, alias_alt)
|
(f.name, f.real_name, alt, f.real_name, alias_alt)
|
||||||
return
|
return
|
||||||
|
|
||||||
def show_usage():
|
def show_usage():
|
||||||
|
@@ -61,6 +61,10 @@
|
|||||||
static GLboolean WarnFlag = GL_FALSE;
|
static GLboolean WarnFlag = GL_FALSE;
|
||||||
static _glapi_warning_func warning_func;
|
static _glapi_warning_func warning_func;
|
||||||
|
|
||||||
|
static void init_glapi_relocs(void);
|
||||||
|
|
||||||
|
static _glapi_proc generate_entrypoint(GLuint functionOffset);
|
||||||
|
static void fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable/disable printing of warning messages.
|
* Enable/disable printing of warning messages.
|
||||||
@@ -133,6 +137,28 @@ static GLint NoOpUnused(void)
|
|||||||
|
|
||||||
#if defined(THREADS)
|
#if defined(THREADS)
|
||||||
|
|
||||||
|
#if defined(GLX_USE_TLS)
|
||||||
|
|
||||||
|
__thread struct _glapi_table * _glapi_tls_Dispatch
|
||||||
|
__attribute__((tls_model("initial-exec")))
|
||||||
|
= (struct _glapi_table *) __glapi_noop_table;
|
||||||
|
|
||||||
|
static __thread struct _glapi_table * _glapi_tls_RealDispatch
|
||||||
|
__attribute__((tls_model("initial-exec")))
|
||||||
|
= (struct _glapi_table *) __glapi_noop_table;
|
||||||
|
|
||||||
|
__thread void * _glapi_tls_Context
|
||||||
|
__attribute__((tls_model("initial-exec")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy per-thread dispatch pointer. This is only needed to support
|
||||||
|
* non-TLS DRI drivers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_glthread_TSD _gl_DispatchTSD;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \name Multi-threaded control support variables
|
* \name Multi-threaded control support variables
|
||||||
*
|
*
|
||||||
@@ -166,6 +192,7 @@ static _glthread_TSD RealDispatchTSD; /**< only when using override */
|
|||||||
static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
|
static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
|
#endif /* defined(GLX_USE_TLS) */
|
||||||
|
|
||||||
#define DISPATCH_TABLE_NAME __glapi_threadsafe_table
|
#define DISPATCH_TABLE_NAME __glapi_threadsafe_table
|
||||||
#define UNUSED_TABLE_NAME __unused_threadsafe_functions
|
#define UNUSED_TABLE_NAME __unused_threadsafe_functions
|
||||||
@@ -184,6 +211,29 @@ static GLint glUnused(void)
|
|||||||
/***** END THREAD-SAFE DISPATCH *****/
|
/***** END THREAD-SAFE DISPATCH *****/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(GLX_USE_TLS)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Old dispatch pointers
|
||||||
|
*
|
||||||
|
* Very old DRI based drivers assume that \c _glapi_Dispatch will never be
|
||||||
|
* \c NULL. Becuase of that, special "thread-safe" dispatch functions are
|
||||||
|
* needed here. Slightly more recent drivers detect the multi-threaded case
|
||||||
|
* by \c _glapi_DispatchTSD being \c NULL.
|
||||||
|
*
|
||||||
|
* \deprecated
|
||||||
|
*
|
||||||
|
* \warning
|
||||||
|
* \c _glapi_RealDispatch does not exist in TLS builds. I don't think it was
|
||||||
|
* ever used outside libGL.so, so this should be safe.
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
PUBLIC const struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
|
||||||
|
PUBLIC const struct _glapi_table *_glapi_DispatchTSD = NULL;
|
||||||
|
PUBLIC const void *_glapi_Context = NULL;
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
PUBLIC struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
|
PUBLIC struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
|
||||||
#if defined( THREADS )
|
#if defined( THREADS )
|
||||||
@@ -191,10 +241,11 @@ PUBLIC struct _glapi_table *_glapi_DispatchTSD = (struct _glapi_table *) __glapi
|
|||||||
#endif
|
#endif
|
||||||
PUBLIC struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;
|
PUBLIC struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;
|
||||||
|
|
||||||
|
|
||||||
/* Used when thread safety disabled */
|
/* Used when thread safety disabled */
|
||||||
PUBLIC void *_glapi_Context = NULL;
|
PUBLIC void *_glapi_Context = NULL;
|
||||||
|
|
||||||
|
#endif /* defined(GLX_USE_TLS) */
|
||||||
|
|
||||||
|
|
||||||
static GLboolean DispatchOverride = GL_FALSE;
|
static GLboolean DispatchOverride = GL_FALSE;
|
||||||
|
|
||||||
@@ -224,7 +275,7 @@ str_dup(const char *str)
|
|||||||
PUBLIC void
|
PUBLIC void
|
||||||
_glapi_check_multithread(void)
|
_glapi_check_multithread(void)
|
||||||
{
|
{
|
||||||
#if defined(THREADS)
|
#if defined(THREADS) && !defined(GLX_USE_TLS)
|
||||||
if (!ThreadSafe) {
|
if (!ThreadSafe) {
|
||||||
static unsigned long knownID;
|
static unsigned long knownID;
|
||||||
static GLboolean firstCall = GL_TRUE;
|
static GLboolean firstCall = GL_TRUE;
|
||||||
@@ -255,7 +306,9 @@ PUBLIC void
|
|||||||
_glapi_set_context(void *context)
|
_glapi_set_context(void *context)
|
||||||
{
|
{
|
||||||
(void) __unused_noop_functions; /* silence a warning */
|
(void) __unused_noop_functions; /* silence a warning */
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
_glapi_tls_Context = context;
|
||||||
|
#elif defined(THREADS)
|
||||||
(void) __unused_threadsafe_functions; /* silence a warning */
|
(void) __unused_threadsafe_functions; /* silence a warning */
|
||||||
_glthread_SetTSD(&ContextTSD, context);
|
_glthread_SetTSD(&ContextTSD, context);
|
||||||
_glapi_Context = (ThreadSafe) ? NULL : context;
|
_glapi_Context = (ThreadSafe) ? NULL : context;
|
||||||
@@ -274,7 +327,9 @@ _glapi_set_context(void *context)
|
|||||||
PUBLIC void *
|
PUBLIC void *
|
||||||
_glapi_get_context(void)
|
_glapi_get_context(void)
|
||||||
{
|
{
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
return _glapi_tls_Context;
|
||||||
|
#elif defined(THREADS)
|
||||||
if (ThreadSafe) {
|
if (ThreadSafe) {
|
||||||
return _glthread_GetTSD(&ContextTSD);
|
return _glthread_GetTSD(&ContextTSD);
|
||||||
}
|
}
|
||||||
@@ -294,6 +349,13 @@ _glapi_get_context(void)
|
|||||||
PUBLIC void
|
PUBLIC void
|
||||||
_glapi_set_dispatch(struct _glapi_table *dispatch)
|
_glapi_set_dispatch(struct _glapi_table *dispatch)
|
||||||
{
|
{
|
||||||
|
#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 (!dispatch) {
|
if (!dispatch) {
|
||||||
/* use the no-op functions */
|
/* use the no-op functions */
|
||||||
dispatch = (struct _glapi_table *) __glapi_noop_table;
|
dispatch = (struct _glapi_table *) __glapi_noop_table;
|
||||||
@@ -304,7 +366,15 @@ _glapi_set_dispatch(struct _glapi_table *dispatch)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
if (DispatchOverride) {
|
||||||
|
_glapi_tls_RealDispatch = dispatch;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
|
||||||
|
_glapi_tls_Dispatch = dispatch;
|
||||||
|
}
|
||||||
|
#elif defined(THREADS)
|
||||||
if (DispatchOverride) {
|
if (DispatchOverride) {
|
||||||
_glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
|
_glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
|
||||||
if (ThreadSafe)
|
if (ThreadSafe)
|
||||||
@@ -342,7 +412,13 @@ _glapi_set_dispatch(struct _glapi_table *dispatch)
|
|||||||
PUBLIC struct _glapi_table *
|
PUBLIC struct _glapi_table *
|
||||||
_glapi_get_dispatch(void)
|
_glapi_get_dispatch(void)
|
||||||
{
|
{
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
struct _glapi_table * api = (DispatchOverride)
|
||||||
|
? _glapi_tls_RealDispatch : _glapi_tls_Dispatch;
|
||||||
|
|
||||||
|
assert( api != NULL );
|
||||||
|
return api;
|
||||||
|
#elif defined(THREADS)
|
||||||
if (ThreadSafe) {
|
if (ThreadSafe) {
|
||||||
if (DispatchOverride) {
|
if (DispatchOverride) {
|
||||||
return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
|
return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
|
||||||
@@ -399,7 +475,10 @@ _glapi_begin_dispatch_override(struct _glapi_table *override)
|
|||||||
|
|
||||||
_glapi_set_dispatch(real);
|
_glapi_set_dispatch(real);
|
||||||
|
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
_glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
|
||||||
|
_glapi_tls_Dispatch = override;
|
||||||
|
#elif defined(THREADS)
|
||||||
_glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
|
_glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
|
||||||
if ( ThreadSafe ) {
|
if ( ThreadSafe ) {
|
||||||
_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
|
_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
|
||||||
@@ -424,10 +503,14 @@ _glapi_end_dispatch_override(int layer)
|
|||||||
DispatchOverride = GL_FALSE;
|
DispatchOverride = GL_FALSE;
|
||||||
_glapi_set_dispatch(real);
|
_glapi_set_dispatch(real);
|
||||||
/* the rest of this isn't needed, just play it safe */
|
/* the rest of this isn't needed, just play it safe */
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
_glapi_tls_RealDispatch = NULL;
|
||||||
|
#else
|
||||||
|
# if defined(THREADS)
|
||||||
_glthread_SetTSD(&RealDispatchTSD, NULL);
|
_glthread_SetTSD(&RealDispatchTSD, NULL);
|
||||||
#endif
|
# endif
|
||||||
_glapi_RealDispatch = NULL;
|
_glapi_RealDispatch = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -439,7 +522,9 @@ _glapi_get_override_dispatch(int layer)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (DispatchOverride) {
|
if (DispatchOverride) {
|
||||||
#if defined(THREADS)
|
#if defined(GLX_USE_TLS)
|
||||||
|
return (struct _glapi_table *) _glapi_tls_Dispatch;
|
||||||
|
#elif defined(THREADS)
|
||||||
return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
|
return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
|
||||||
#else
|
#else
|
||||||
return _glapi_Dispatch;
|
return _glapi_Dispatch;
|
||||||
@@ -498,9 +583,15 @@ get_static_proc_offset(const char *funcName)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef USE_X86_ASM
|
#ifdef USE_X86_ASM
|
||||||
extern const GLubyte gl_dispatch_functions_start[];
|
|
||||||
|
|
||||||
# if defined(THREADS)
|
#if defined( GLX_USE_TLS )
|
||||||
|
extern GLubyte gl_dispatch_functions_start[];
|
||||||
|
extern GLubyte gl_dispatch_functions_end[];
|
||||||
|
#else
|
||||||
|
extern const GLubyte gl_dispatch_functions_start[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# if defined(THREADS) && !defined(GLX_USE_TLS)
|
||||||
# define X86_DISPATCH_FUNCTION_SIZE 32
|
# define X86_DISPATCH_FUNCTION_SIZE 32
|
||||||
# else
|
# else
|
||||||
# define X86_DISPATCH_FUNCTION_SIZE 16
|
# define X86_DISPATCH_FUNCTION_SIZE 16
|
||||||
@@ -603,45 +694,20 @@ static _glapi_proc
|
|||||||
generate_entrypoint(GLuint functionOffset)
|
generate_entrypoint(GLuint functionOffset)
|
||||||
{
|
{
|
||||||
#if defined(USE_X86_ASM)
|
#if defined(USE_X86_ASM)
|
||||||
/*
|
/* 32 is chosen as something of a magic offset. For x86, the dispatch
|
||||||
* This x86 code contributed by Josh Vanderhoof.
|
* at offset 32 is the first one where the offset in the
|
||||||
*
|
* "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
|
||||||
* 0: a1 10 32 54 76 movl __glapi_Dispatch,%eax
|
|
||||||
* 00 01 02 03 04
|
|
||||||
* 5: 85 c0 testl %eax,%eax
|
|
||||||
* 05 06
|
|
||||||
* 7: 74 06 je f <entrypoint+0xf>
|
|
||||||
* 07 08
|
|
||||||
* 9: ff a0 10 32 54 76 jmp *0x76543210(%eax)
|
|
||||||
* 09 0a 0b 0c 0d 0e
|
|
||||||
* f: e8 fc ff ff ff call __glapi_get_dispatch
|
|
||||||
* 0f 10 11 12 13
|
|
||||||
* 14: ff a0 10 32 54 76 jmp *0x76543210(%eax)
|
|
||||||
* 14 15 16 17 18 19
|
|
||||||
*/
|
*/
|
||||||
static const unsigned char insn_template[] = {
|
const GLubyte * const template_func = gl_dispatch_functions_start
|
||||||
0xa1, 0x00, 0x00, 0x00, 0x00,
|
+ (X86_DISPATCH_FUNCTION_SIZE * 32);
|
||||||
0x85, 0xc0,
|
GLubyte * const code = (GLubyte *) malloc( X86_DISPATCH_FUNCTION_SIZE );
|
||||||
0x74, 0x06,
|
|
||||||
0xff, 0xa0, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xe8, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xa0, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
unsigned char *code = (unsigned char *) malloc(sizeof(insn_template));
|
|
||||||
unsigned int next_insn;
|
|
||||||
if (code) {
|
|
||||||
memcpy(code, insn_template, sizeof(insn_template));
|
|
||||||
|
|
||||||
#if defined( THREADS )
|
|
||||||
*(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_DispatchTSD;
|
if ( code != NULL ) {
|
||||||
#else
|
(void) memcpy( code, template_func, X86_DISPATCH_FUNCTION_SIZE );
|
||||||
*(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_Dispatch;
|
fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
|
||||||
#endif
|
|
||||||
*(unsigned int *)(code + 0x0b) = (unsigned int)functionOffset * 4;
|
|
||||||
next_insn = (unsigned int)(code + 0x14);
|
|
||||||
*(unsigned int *)(code + 0x10) = (unsigned int)_glapi_get_dispatch - next_insn;
|
|
||||||
*(unsigned int *)(code + 0x16) = (unsigned int)functionOffset * 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_glapi_proc) code;
|
return (_glapi_proc) code;
|
||||||
#elif defined(USE_SPARC_ASM)
|
#elif defined(USE_SPARC_ASM)
|
||||||
|
|
||||||
@@ -707,10 +773,19 @@ static void
|
|||||||
fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
|
fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
|
||||||
{
|
{
|
||||||
#if defined(USE_X86_ASM)
|
#if defined(USE_X86_ASM)
|
||||||
|
GLubyte * const code = (GLubyte *) entrypoint;
|
||||||
|
|
||||||
unsigned char *code = (unsigned char *) entrypoint;
|
|
||||||
*(unsigned int *)(code + 0x0b) = offset * 4;
|
#if X86_DISPATCH_FUNCTION_SIZE == 32
|
||||||
*(unsigned int *)(code + 0x16) = offset * 4;
|
*((unsigned int *)(code + 11)) = 4 * offset;
|
||||||
|
*((unsigned int *)(code + 22)) = 4 * offset;
|
||||||
|
#elif X86_DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
|
||||||
|
*((unsigned int *)(code + 8)) = 4 * offset;
|
||||||
|
#elif X86_DISPATCH_FUNCTION_SIZE == 16
|
||||||
|
*((unsigned int *)(code + 7)) = 4 * offset;
|
||||||
|
#else
|
||||||
|
# error Invalid X86_DISPATCH_FUNCTION_SIZE!
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif defined(USE_SPARC_ASM)
|
#elif defined(USE_SPARC_ASM)
|
||||||
|
|
||||||
@@ -1028,3 +1103,25 @@ _glapi_check_table(const struct _glapi_table *table)
|
|||||||
(void) table;
|
(void) table;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform platform-specific GL API entry-point fixups.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
init_glapi_relocs( void )
|
||||||
|
{
|
||||||
|
#if defined( USE_X86_ASM ) && defined( GLX_USE_TLS )
|
||||||
|
extern void * _x86_get_dispatch(void);
|
||||||
|
const GLubyte * const get_disp = (const GLubyte *) _x86_get_dispatch;
|
||||||
|
GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start;
|
||||||
|
|
||||||
|
|
||||||
|
while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) {
|
||||||
|
(void) memcpy( curr_func, get_disp, 6 );
|
||||||
|
curr_func += X86_DISPATCH_FUNCTION_SIZE;
|
||||||
|
}
|
||||||
|
#endif /* defined( USE_X86_ASM ) && defined( GLX_USE_TLS ) */
|
||||||
|
}
|
||||||
|
@@ -54,10 +54,17 @@ typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...);
|
|||||||
typedef void (*_glapi_proc)(void); /* generic function pointer */
|
typedef void (*_glapi_proc)(void); /* generic function pointer */
|
||||||
|
|
||||||
|
|
||||||
extern void *_glapi_Context;
|
#if defined (GLX_USE_TLS)
|
||||||
|
|
||||||
|
const extern void *_glapi_Context;
|
||||||
|
const extern struct _glapi_table *_glapi_Dispatch;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
extern void *_glapi_Context;
|
||||||
extern struct _glapi_table *_glapi_Dispatch;
|
extern struct _glapi_table *_glapi_Dispatch;
|
||||||
|
|
||||||
|
#endif /* defined (GLX_USE_TLS) */
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_glapi_noop_enable_warnings(GLboolean enable);
|
_glapi_noop_enable_warnings(GLboolean enable);
|
||||||
|
@@ -306,7 +306,14 @@ _glthread_GetTSD(_glthread_TSD *);
|
|||||||
extern void
|
extern void
|
||||||
_glthread_SetTSD(_glthread_TSD *, void *);
|
_glthread_SetTSD(_glthread_TSD *, void *);
|
||||||
|
|
||||||
#ifndef GL_CALL
|
#if defined(GLX_USE_TLS)
|
||||||
|
|
||||||
|
extern __thread struct _glapi_table * _glapi_tls_Dispatch
|
||||||
|
__attribute__((tls_model("initial-exec")));
|
||||||
|
|
||||||
|
# define GL_CALL(name) (*(_glapi_tls_Dispatch-> name))
|
||||||
|
|
||||||
|
#elif !defined(GL_CALL)
|
||||||
# if defined(THREADS)
|
# if defined(THREADS)
|
||||||
extern struct _glapi_table * _glapi_DispatchTSD;
|
extern struct _glapi_table * _glapi_DispatchTSD;
|
||||||
# define GL_CALL(name) \
|
# define GL_CALL(name) \
|
||||||
|
@@ -33,7 +33,10 @@
|
|||||||
* the symbol visibility mode to 'default'.
|
* the symbol visibility mode to 'default'.
|
||||||
*/
|
*/
|
||||||
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
|
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
|
||||||
#pragma GCC visibility push(default)
|
# pragma GCC visibility push(default)
|
||||||
|
# define HIDDEN(x) .hidden x
|
||||||
|
#else
|
||||||
|
# define HIDDEN(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __WIN32__
|
#ifndef __WIN32__
|
||||||
@@ -64,7 +67,17 @@
|
|||||||
# define THREADS
|
# define THREADS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PTHREADS)
|
#ifdef GLX_USE_TLS
|
||||||
|
|
||||||
|
# define GL_STUB(fn,off,fn_alt) \
|
||||||
|
ALIGNTEXT16; \
|
||||||
|
GLOBL_FN(GL_PREFIX(fn, fn_alt)); \
|
||||||
|
GL_PREFIX(fn, fn_alt): \
|
||||||
|
CALL(_x86_get_dispatch) ; \
|
||||||
|
NOP ; \
|
||||||
|
JMP(GL_OFFSET(off))
|
||||||
|
|
||||||
|
#elif defined(PTHREADS)
|
||||||
# define GL_STUB(fn,off,fn_alt) \
|
# define GL_STUB(fn,off,fn_alt) \
|
||||||
ALIGNTEXT16; \
|
ALIGNTEXT16; \
|
||||||
GLOBL_FN(GL_PREFIX(fn, fn_alt)); \
|
GLOBL_FN(GL_PREFIX(fn, fn_alt)); \
|
||||||
@@ -106,7 +119,16 @@ GL_PREFIX(fn, fn_alt): \
|
|||||||
|
|
||||||
SEG_TEXT
|
SEG_TEXT
|
||||||
|
|
||||||
#ifdef PTHREADS
|
#ifdef GLX_USE_TLS
|
||||||
|
|
||||||
|
GLOBL GLNAME(_x86_get_dispatch)
|
||||||
|
HIDDEN(GLNAME(_x86_get_dispatch))
|
||||||
|
ALIGNTEXT16
|
||||||
|
GLNAME(_x86_get_dispatch):
|
||||||
|
movl %gs:_glapi_tls_Dispatch@NTPOFF, %eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
#elif defined(PTHREADS)
|
||||||
EXTERN GLNAME(_glapi_Dispatch)
|
EXTERN GLNAME(_glapi_Dispatch)
|
||||||
EXTERN GLNAME(_gl_DispatchTSD)
|
EXTERN GLNAME(_gl_DispatchTSD)
|
||||||
EXTERN GLNAME(pthread_getspecific)
|
EXTERN GLNAME(pthread_getspecific)
|
||||||
@@ -122,7 +144,13 @@ GLNAME(_x86_get_dispatch):
|
|||||||
EXTERN GLNAME(_glapi_get_dispatch)
|
EXTERN GLNAME(_glapi_get_dispatch)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ALIGNTEXT16 ; GLOBL GLNAME(gl_dispatch_functions_start)
|
#if defined( GLX_USE_TLS )
|
||||||
|
.section wtext, "awx", @progbits
|
||||||
|
#endif /* defined( GLX_USE_TLS ) */
|
||||||
|
|
||||||
|
ALIGNTEXT16
|
||||||
|
GLOBL GLNAME(gl_dispatch_functions_start)
|
||||||
|
HIDDEN(GLNAME(gl_dispatch_functions_start))
|
||||||
GLNAME(gl_dispatch_functions_start):
|
GLNAME(gl_dispatch_functions_start):
|
||||||
|
|
||||||
GL_STUB(NewList, _gloffset_NewList, NewList@8)
|
GL_STUB(NewList, _gloffset_NewList, NewList@8)
|
||||||
@@ -1120,4 +1148,22 @@ GLNAME(gl_dispatch_functions_start):
|
|||||||
GL_STUB_ALIAS(PointParameterfSGIS, _gloffset_PointParameterfEXT, PointParameterfSGIS@8, PointParameterfEXT, PointParameterfEXT@8)
|
GL_STUB_ALIAS(PointParameterfSGIS, _gloffset_PointParameterfEXT, PointParameterfSGIS@8, PointParameterfEXT, PointParameterfEXT@8)
|
||||||
GL_STUB_ALIAS(PointParameterfvSGIS, _gloffset_PointParameterfvEXT, PointParameterfvSGIS@8, PointParameterfvEXT, PointParameterfvEXT@8)
|
GL_STUB_ALIAS(PointParameterfvSGIS, _gloffset_PointParameterfvEXT, PointParameterfvSGIS@8, PointParameterfvEXT, PointParameterfvEXT@8)
|
||||||
|
|
||||||
|
GLOBL GLNAME(gl_dispatch_functions_end)
|
||||||
|
HIDDEN(GLNAME(gl_dispatch_functions_end))
|
||||||
|
ALIGNTEXT16
|
||||||
|
GLNAME(gl_dispatch_functions_end):
|
||||||
|
|
||||||
|
#if defined(GLX_USE_TLS) && defined(__linux__)
|
||||||
|
.section ".note.ABI-tag", "a"
|
||||||
|
.p2align 2
|
||||||
|
.long 1f - 0f /* name length */
|
||||||
|
.long 3f - 2f /* data length */
|
||||||
|
.long 1 /* note length */
|
||||||
|
0: .asciz "GNU" /* vendor name */
|
||||||
|
1: .p2align 2
|
||||||
|
2: .long 0 /* note data: the ABI tag */
|
||||||
|
.long 2,4,20 /* Minimum kernel version w/TLS */
|
||||||
|
3: .p2align 2 /* pad out section */
|
||||||
|
#endif /* GLX_USE_TLS */
|
||||||
|
|
||||||
#endif /* __WIN32__ */
|
#endif /* __WIN32__ */
|
||||||
|
Reference in New Issue
Block a user