-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Chia-I Wu wrote:
> There is a possbile race that _glapi_Context is reset by another thread
> after it is tested in GET_CURRENT_CONTEXT but before it is returned. To
> avoid the race in a lockless fashion, no threads should reset
> _glapi_Context (or _glapi_Dispatch).
>
> This patch renames ThreadSafe to _glapi_ThreadSafe and makes it global
> so that it can be tested for thread-safe mode. This also removes a
> __builtin_expect so that multithreaded apps are not punished.
> ---
> src/mesa/glapi/glapi.c | 32 ++++++++++++++++----------------
> src/mesa/glapi/glapi.h | 3 ++-
> src/mesa/glapi/glthread.h | 2 +-
> 3 files changed, 19 insertions(+), 18 deletions(-)
>
> diff --git a/src/mesa/glapi/glapi.c b/src/mesa/glapi/glapi.c
> index b9ab9c0..b05f80c 100644
> --- a/src/mesa/glapi/glapi.c
> +++ b/src/mesa/glapi/glapi.c
> @@ -172,8 +172,8 @@ static GLint NoOpUnused(void)
> * There is a race condition in setting \c _glapi_Dispatch 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_TRUE, is
> - * used to determine whether or not the application is multithreaded.
> + * of that, \c _glapi_ThreadSafe, which can only ever be changed to \c
> GL_TRUE,
> + * is used to determine whether or not the application is multithreaded.
> *
> * In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context
> are
> * hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch
> and
> @@ -199,7 +199,7 @@ PUBLIC const void *_glapi_Context = NULL;
> #if defined(THREADS)
>
> _glthread_DECLARE_STATIC_MUTEX(ThreadCheckMutex);
> -static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
> +GLboolean _glapi_ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
I've never been a fan of this variable name. Unless Brian objects, I'd
like to see this changed to _glapi_SingleThreaded or something similar.
That makes the real meaning a bit more clear, I think. Also, shouldn't
this be declared volatile? (I'm not 100% sure one way or the other.)
> _glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
> static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
>
> @@ -235,7 +235,7 @@ _glapi_check_multithread(void)
> static unsigned long knownID;
> static GLboolean firstCall = GL_TRUE;
>
> - if (ThreadSafe)
> + if (_glapi_ThreadSafe)
> return;
>
> _glthread_LOCK_MUTEX(ThreadCheckMutex);
> @@ -248,9 +248,12 @@ _glapi_check_multithread(void)
> firstCall = GL_FALSE;
> }
> else if (knownID != _glthread_GetID()) {
> - ThreadSafe = GL_TRUE;
> - _glapi_set_dispatch(NULL);
> - _glapi_set_context(NULL);
> + /*
> + * switch to thread-safe mode. _glapi_Context and _glapi_Dispatch are
> no
> + * longer accessed after this point, except for raced by the first
> + * thread. Because of the race, they cannot be reset.
> + */
> + _glapi_ThreadSafe = GL_TRUE;
> }
> _glthread_UNLOCK_MUTEX(ThreadCheckMutex);
> #endif
> @@ -270,8 +273,9 @@ _glapi_set_context(void *context)
> #if defined(GLX_USE_TLS)
> _glapi_tls_Context = context;
> #elif defined(THREADS)
> + if (!_glapi_ThreadSafe)
> + _glapi_Context = context;
> _glthread_SetTSD(&ContextTSD, context);
> - _glapi_Context = (ThreadSafe) ? NULL : context;
> #else
> _glapi_Context = context;
> #endif
> @@ -290,12 +294,7 @@ _glapi_get_context(void)
> #if defined(GLX_USE_TLS)
> return _glapi_tls_Context;
> #elif defined(THREADS)
> - if (ThreadSafe) {
> - return _glthread_GetTSD(&ContextTSD);
> - }
> - else {
> - return _glapi_Context;
> - }
> + return (_glapi_ThreadSafe) ? _glthread_GetTSD(&ContextTSD) :
> _glapi_Context;
> #else
> return _glapi_Context;
> #endif
> @@ -510,8 +509,9 @@ _glapi_set_dispatch(struct _glapi_table *dispatch)
> #if defined(GLX_USE_TLS)
> _glapi_tls_Dispatch = dispatch;
> #elif defined(THREADS)
> + if (!_glapi_ThreadSafe)
> + _glapi_Dispatch = dispatch;
> _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
> - _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch;
> #else /*THREADS*/
> _glapi_Dispatch = dispatch;
> #endif /*THREADS*/
> @@ -529,7 +529,7 @@ _glapi_get_dispatch(void)
> #if defined(GLX_USE_TLS)
> api = _glapi_tls_Dispatch;
> #elif defined(THREADS)
> - api = (ThreadSafe)
> + api = (_glapi_ThreadSafe)
> ? (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD)
> : _glapi_Dispatch;
> #else
> diff --git a/src/mesa/glapi/glapi.h b/src/mesa/glapi/glapi.h
> index 8f2cf66..e935195 100644
> --- a/src/mesa/glapi/glapi.h
> +++ b/src/mesa/glapi/glapi.h
> @@ -91,10 +91,11 @@ extern __thread void * _glapi_tls_Context
> #else
>
> extern void *_glapi_Context;
> +extern GLboolean _glapi_ThreadSafe;
> extern struct _glapi_table *_glapi_Dispatch;
>
> # ifdef THREADS
> -# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *)
> (_glapi_Context ? _glapi_Context : _glapi_get_context())
> +# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *)
> ((!_glapi_ThreadSafe) ? _glapi_Context : _glapi_get_context())
> # else
> # define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) _glapi_Context
> # endif
> diff --git a/src/mesa/glapi/glthread.h b/src/mesa/glapi/glthread.h
> index dfe09a9..5b19883 100644
> --- a/src/mesa/glapi/glthread.h
> +++ b/src/mesa/glapi/glthread.h
> @@ -364,7 +364,7 @@ extern __thread struct _glapi_table * _glapi_tls_Dispatch
> #elif !defined(GL_CALL)
> # if defined(THREADS)
> # define GET_DISPATCH() \
> - ((__builtin_expect( _glapi_Dispatch != NULL, 1 )) \
> + ((!_glapi_ThreadSafe) \
> ? _glapi_Dispatch : _glapi_get_dispatch())
Keep the __builtin_expect. Applications almost always use OpenGL from a
single thread even if the application is multithreaded.
> # else
> # define GET_DISPATCH() _glapi_Dispatch
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkpXj/EACgkQX1gOwKyEAw89LwCeMeBmEfJpdiqXa7WKyphV6DCA
pI0AnAuZK2Q718ZBtkXbTiiiK4eCUqmi
=/3jW
-----END PGP SIGNATURE-----
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Mesa3d-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev