diff options
-rw-r--r-- | src/mesa/glapi/glapi.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/src/mesa/glapi/glapi.c b/src/mesa/glapi/glapi.c index 2a083949fe0..1f640e3e10e 100644 --- a/src/mesa/glapi/glapi.c +++ b/src/mesa/glapi/glapi.c @@ -155,10 +155,15 @@ static int NoOpUnused(void) * static dispatch functions to call \c _glapi_get_dispatch to get the real * dispatch table. * - * Throughout the code \c _glapi_DispatchTSD == \c NULL is used to determine - * whether or not the application is multi-threaded. + * There is a race condition in setting \c _glapi_DispatchTSD to \c NULL. + * It is possible for the original thread to be setting it at the same instant + * a new thread, perhaps running on a different processor, is clearing it. + * Because of that, \c ThreadSafe, which can only ever be changed to + * \c GL_FALSE, is used to determin whether or not the application is + * multithreaded. */ /*@{*/ +static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */ _glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */ static _glthread_TSD RealDispatchTSD; /**< only when using override */ static _glthread_TSD ContextTSD; /**< Per-thread context pointer */ @@ -184,9 +189,12 @@ static int glUnused(void) struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table; +#if defined( THREADS ) struct _glapi_table *_glapi_DispatchTSD = (struct _glapi_table *) __glapi_noop_table; +#endif struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table; + /* Used when thread safety disabled */ void *_glapi_Context = NULL; @@ -219,7 +227,7 @@ void _glapi_check_multithread(void) { #if defined(THREADS) - if ( _glapi_DispatchTSD != NULL ) { + if (!ThreadSafe) { static unsigned long knownID; static GLboolean firstCall = GL_TRUE; if (firstCall) { @@ -227,6 +235,7 @@ _glapi_check_multithread(void) firstCall = GL_FALSE; } else if (knownID != _glthread_GetID()) { + ThreadSafe = GL_TRUE; _glapi_set_dispatch(NULL); } } @@ -249,7 +258,7 @@ _glapi_set_context(void *context) { #if defined(THREADS) _glthread_SetTSD(&ContextTSD, context); - _glapi_Context = (_glapi_DispatchTSD == NULL) ? NULL : context; + _glapi_Context = (ThreadSafe) ? NULL : context; #else _glapi_Context = context; #endif @@ -266,7 +275,7 @@ void * _glapi_get_context(void) { #if defined(THREADS) - if ( _glapi_DispatchTSD == NULL ) { + if (ThreadSafe) { return _glthread_GetTSD(&ContextTSD); } else { @@ -303,7 +312,7 @@ _glapi_set_dispatch(struct _glapi_table *dispatch) #if defined(THREADS) if (DispatchOverride) { _glthread_SetTSD(&RealDispatchTSD, (void *) old_style_dispatch); - if ( dispatch == NULL ) + if (ThreadSafe) _glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table; else _glapi_RealDispatch = dispatch; @@ -311,11 +320,14 @@ _glapi_set_dispatch(struct _glapi_table *dispatch) else { /* normal operation */ _glthread_SetTSD(&_gl_DispatchTSD, (void *) old_style_dispatch); - _glapi_DispatchTSD = dispatch; - - _glapi_Dispatch = (dispatch == NULL) - ? (struct _glapi_table *) __glapi_threadsafe_table - : old_style_dispatch; + if (ThreadSafe) { + _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table; + _glapi_DispatchTSD = NULL; + } + else { + _glapi_Dispatch = old_style_dispatch; + _glapi_DispatchTSD = dispatch; + } } #else /*THREADS*/ if (DispatchOverride) { @@ -336,7 +348,7 @@ struct _glapi_table * _glapi_get_dispatch(void) { #if defined(THREADS) - if ( _glapi_DispatchTSD == NULL ) { + if (ThreadSafe) { if (DispatchOverride) { return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD); } @@ -394,8 +406,9 @@ _glapi_begin_dispatch_override(struct _glapi_table *override) #if defined(THREADS) _glthread_SetTSD(&_gl_DispatchTSD, (void *) override); - if ( _glapi_DispatchTSD == NULL ) { + if ( ThreadSafe ) { _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table; + _glapi_DispatchTSD = NULL; } else { _glapi_Dispatch = override; |