* 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 */
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;
_glapi_check_multithread(void)
{
#if defined(THREADS)
- if ( _glapi_DispatchTSD != NULL ) {
+ if (!ThreadSafe) {
static unsigned long knownID;
static GLboolean firstCall = GL_TRUE;
if (firstCall) {
firstCall = GL_FALSE;
}
else if (knownID != _glthread_GetID()) {
+ ThreadSafe = GL_TRUE;
_glapi_set_dispatch(NULL);
}
}
{
#if defined(THREADS)
_glthread_SetTSD(&ContextTSD, context);
- _glapi_Context = (_glapi_DispatchTSD == NULL) ? NULL : context;
+ _glapi_Context = (ThreadSafe) ? NULL : context;
#else
_glapi_Context = context;
#endif
_glapi_get_context(void)
{
#if defined(THREADS)
- if ( _glapi_DispatchTSD == NULL ) {
+ if (ThreadSafe) {
return _glthread_GetTSD(&ContextTSD);
}
else {
#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;
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) {
_glapi_get_dispatch(void)
{
#if defined(THREADS)
- if ( _glapi_DispatchTSD == NULL ) {
+ if (ThreadSafe) {
if (DispatchOverride) {
return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
}
#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;