summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/glapi/glapi.c39
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;