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:
Ian Romanick 2005-04-18 16:59:53 +00:00
parent 2e823f29e4
commit 02986cb2cc
2 changed files with 104 additions and 9 deletions

View file

@ -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()

View file

@ -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) {