mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
Add support for pthreads and TLS to libGL for __glXLock / __glXUnlock and
for tracking the current GLX context. This fixes bug #3024.
This commit is contained in:
parent
2e823f29e4
commit
02986cb2cc
2 changed files with 104 additions and 9 deletions
|
|
@ -60,8 +60,10 @@
|
|||
#include "GL/internal/glcore.h"
|
||||
#include "glapitable.h"
|
||||
#include "glxextensions.h"
|
||||
#ifdef XTHREADS
|
||||
#include "Xthreads.h"
|
||||
#if defined( XTHREADS )
|
||||
# include "Xthreads.h"
|
||||
#elif defined( PTHREADS )
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
#ifdef GLX_BUILT_IN_XMESA
|
||||
#include "realglx.h" /* just silences prototype warnings */
|
||||
|
|
@ -625,24 +627,44 @@ extern __GLXdisplayPrivate *__glXInitialize(Display*);
|
|||
extern int __glXDebug;
|
||||
|
||||
/* This is per-thread storage in an MT environment */
|
||||
#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
|
||||
extern __GLXcontext *__glXGetCurrentContext(void);
|
||||
#if defined( XTHREADS ) || defined( PTHREADS )
|
||||
|
||||
extern void __glXSetCurrentContext(__GLXcontext *c);
|
||||
|
||||
# if defined( GLX_USE_TLS )
|
||||
|
||||
extern __thread void * __glX_tls_Context
|
||||
__attribute__((tls_model("initial-exec")));
|
||||
|
||||
# define __glXGetCurrentContext() __glX_tls_Context
|
||||
|
||||
# else
|
||||
|
||||
extern __GLXcontext *__glXGetCurrentContext(void);
|
||||
|
||||
# endif /* defined( GLX_USE_TLS ) */
|
||||
|
||||
#else
|
||||
|
||||
extern __GLXcontext *__glXcurrentContext;
|
||||
#define __glXGetCurrentContext() __glXcurrentContext
|
||||
#define __glXSetCurrentContext(gc) __glXcurrentContext = gc
|
||||
#endif
|
||||
|
||||
#endif /* defined( XTHREADS ) || defined( PTHREADS ) */
|
||||
|
||||
|
||||
/*
|
||||
** Global lock for all threads in this address space using the GLX
|
||||
** extension
|
||||
*/
|
||||
#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
|
||||
#if defined( XTHREADS )
|
||||
extern xmutex_rec __glXmutex;
|
||||
#define __glXLock() xmutex_lock(&__glXmutex)
|
||||
#define __glXUnlock() xmutex_unlock(&__glXmutex)
|
||||
#elif defined( PTHREADS )
|
||||
extern pthread_mutex_t __glXmutex;
|
||||
#define __glXLock() pthread_mutex_lock(&__glXmutex)
|
||||
#define __glXUnlock() pthread_mutex_unlock(&__glXmutex)
|
||||
#else
|
||||
#define __glXLock()
|
||||
#define __glXUnlock()
|
||||
|
|
|
|||
|
|
@ -52,7 +52,9 @@
|
|||
#include "indirect_init.h"
|
||||
#include "glapi.h"
|
||||
#ifdef XTHREADS
|
||||
#include "Xthreads.h"
|
||||
# include "Xthreads.h"
|
||||
#elif defined(PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
#include "glxextensions.h"
|
||||
#include "glcontextmodes.h"
|
||||
|
|
@ -138,7 +140,7 @@ static __GLapi *IndirectAPI = NULL;
|
|||
* Current context management and locking
|
||||
*/
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
|
||||
#if defined( XTHREADS )
|
||||
|
||||
/* thread safe */
|
||||
static GLboolean TSDinitialized = GL_FALSE;
|
||||
|
|
@ -174,6 +176,77 @@ void __glXSetCurrentContext(__GLXcontext *c)
|
|||
/* Used by the __glXLock() and __glXUnlock() macros */
|
||||
xmutex_rec __glXmutex;
|
||||
|
||||
#elif defined( PTHREADS )
|
||||
|
||||
pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
# if defined( GLX_USE_TLS )
|
||||
|
||||
/**
|
||||
* Per-thread GLX context pointer.
|
||||
*
|
||||
* \c __glXSetCurrentContext is written is such a way that this pointer can
|
||||
* \b never be \c NULL. This is important! Because of this
|
||||
* \c __glXGetCurrentContext can be implemented as trivial macro.
|
||||
*/
|
||||
__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec")))
|
||||
= &dummyContext;
|
||||
|
||||
void __glXSetCurrentContext( __GLXcontext * c )
|
||||
{
|
||||
__glX_tls_Context = (c != NULL) ? c : &dummyContext;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
/**
|
||||
* Per-thread data key.
|
||||
*
|
||||
* Once \c init_thread_data has been called, the per-thread data key will
|
||||
* take a value of \c NULL. As each new thread is created the default
|
||||
* value, in that thread, will be \c NULL.
|
||||
*/
|
||||
static pthread_key_t ContextTSD;
|
||||
|
||||
/**
|
||||
* Initialize the per-thread data key.
|
||||
*
|
||||
* This function is called \b exactly once per-process (not per-thread!) to
|
||||
* initialize the per-thread data key. This is ideally done using the
|
||||
* \c pthread_once mechanism.
|
||||
*/
|
||||
static void init_thread_data( void )
|
||||
{
|
||||
if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) {
|
||||
perror( "pthread_key_create" );
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
void __glXSetCurrentContext( __GLXcontext * c )
|
||||
{
|
||||
pthread_once( & once_control, init_thread_data );
|
||||
pthread_setspecific( ContextTSD, c );
|
||||
}
|
||||
|
||||
__GLXcontext * __glXGetCurrentContext( void )
|
||||
{
|
||||
void * v;
|
||||
|
||||
pthread_once( & once_control, init_thread_data );
|
||||
|
||||
v = pthread_getspecific( ContextTSD );
|
||||
return (v == NULL) ? & dummyContext : (__GLXcontext *) v;
|
||||
}
|
||||
|
||||
# endif /* defined( GLX_USE_TLS ) */
|
||||
|
||||
#elif defined( THREADS )
|
||||
|
||||
#error Unknown threading method specified.
|
||||
|
||||
#else
|
||||
|
||||
/* not thread safe */
|
||||
|
|
@ -1119,7 +1192,7 @@ __GLXdisplayPrivate *__glXInitialize(Display* dpy)
|
|||
XEDataObject dataObj;
|
||||
int major, minor;
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
|
||||
#if defined(XTHREADS)
|
||||
{
|
||||
static int firstCall = 1;
|
||||
if (firstCall) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue