summaryrefslogtreecommitdiff
path: root/src/egl/main/eglcurrent.c
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2009-08-10 12:20:31 +0800
committerBrian Paul <brianp@vmware.com>2009-08-11 22:14:35 -0600
commitf6c2f5e37925abe3ea7036b7a3bd6ca1721e4f73 (patch)
tree665e49ffb7235272024e3a3f1de3051183b96e17 /src/egl/main/eglcurrent.c
parente79d21ca1f11e5b584db0930eb0cf49869b0e77d (diff)
egl: Destroy eglThreadInfo on thread exit.
This is done through pthread TSD destructor. It destroys all thread infos except for main thread's. The thread info of the main thread is destroyed by _eglFiniCurrent. TLS case is not supported yet. Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Diffstat (limited to 'src/egl/main/eglcurrent.c')
-rw-r--r--src/egl/main/eglcurrent.c89
1 files changed, 73 insertions, 16 deletions
diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
index 96152db19f..e1b3548517 100644
--- a/src/egl/main/eglcurrent.c
+++ b/src/egl/main/eglcurrent.c
@@ -3,6 +3,7 @@
#include "eglcurrent.h"
#include "eglcontext.h"
#include "egllog.h"
+#include "eglmutex.h"
/* a fallback thread info to guarantee that every thread always has one */
@@ -13,51 +14,108 @@ static _EGLThreadInfo dummy_thread;
static __thread const _EGLThreadInfo *_egl_TSD;
__attribute__ ((tls_model("initial-exec")));
-static INLINE EGLBoolean _eglInitTSD(void) { return EGL_TRUE; }
-static INLINE void _eglFiniTSD(void) { }
-static INLINE void _eglSetTSD(const _EGLThreadInfo *t) { _egl_TSD = t; }
+static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
+{
+ _egl_TSD = t;
+}
static INLINE _EGLThreadInfo *_eglGetTSD(void)
{
return (_EGLThreadInfo *) _egl_TSD;
}
+static INLINE void _eglFiniTSD(void)
+{
+}
+
+static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
+{
+ /* TODO destroy TSD */
+ (void) dtor;
+ return EGL_TRUE;
+}
+
#elif PTHREADS
#include <pthread.h>
+static _EGL_DECLARE_MUTEX(_egl_TSDMutex);
+static EGLBoolean _egl_TSDInitialized;
static pthread_key_t _egl_TSD;
+static void (*_egl_FreeTSD)(_EGLThreadInfo *);
-static INLINE EGLBoolean _eglInitTSD(void)
+static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
{
- return (pthread_key_create(&_egl_TSD, NULL) == 0);
+ pthread_setspecific(_egl_TSD, (const void *) t);
}
-static INLINE void _eglFiniTSD(void)
+static INLINE _EGLThreadInfo *_eglGetTSD(void)
{
- pthread_key_delete(_egl_TSD);
+ return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD);
}
-static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
+static INLINE void _eglFiniTSD(void)
{
- pthread_setspecific(_egl_TSD, (const void *) t);
+ _eglLockMutex(&_egl_TSDMutex);
+ if (_egl_TSDInitialized) {
+ _EGLThreadInfo *t = _eglGetTSD();
+
+ _egl_TSDInitialized = EGL_FALSE;
+ if (t && _egl_FreeTSD)
+ _egl_FreeTSD((void *) t);
+ pthread_key_delete(_egl_TSD);
+ }
+ _eglUnlockMutex(&_egl_TSDMutex);
}
-static INLINE _EGLThreadInfo *_eglGetTSD(void)
+static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
{
- return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD);
+ if (!_egl_TSDInitialized) {
+ _eglLockMutex(&_egl_TSDMutex);
+
+ /* check again after acquiring lock */
+ if (!_egl_TSDInitialized) {
+ if (pthread_key_create(&_egl_TSD, (void (*)(void *)) dtor) != 0) {
+ _eglUnlockMutex(&_egl_TSDMutex);
+ return EGL_FALSE;
+ }
+ _egl_FreeTSD = dtor;
+ _egl_TSDInitialized = EGL_TRUE;
+ }
+
+ _eglUnlockMutex(&_egl_TSDMutex);
+ }
+
+ return EGL_TRUE;
}
#else /* PTHREADS */
static const _EGLThreadInfo *_egl_TSD;
+static void (*_egl_FreeTSD)(_EGLThreadInfo *);
-static INLINE EGLBoolean _eglInitTSD(void) { return EGL_TRUE; }
-static INLINE void _eglFiniTSD(void) { }
-static INLINE void _eglSetTSD(const _EGLThreadInfo *t) { _egl_TSD = t; }
+static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
+{
+ _egl_TSD = t;
+}
static INLINE _EGLThreadInfo *_eglGetTSD(void)
{
return (_EGLThreadInfo *) _egl_TSD;
}
+
+static INLINE void _eglFiniTSD(void)
+{
+ if (_egl_FreeTSD && _egl_TSD)
+ _egl_FreeTSD((_EGLThreadInfo *) _egl_TSD);
+}
+
+static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
+{
+ if (!_egl_FreeTSD && dtor) {
+ _egl_FreeTSD = dtor;
+ }
+ return EGL_TRUE;
+}
+
#endif /* !PTHREADS */
@@ -104,7 +162,7 @@ EGLBoolean
_eglInitCurrent(void)
{
_eglInitThreadInfo(&dummy_thread);
- return _eglInitTSD();
+ return _eglInitTSD((void (*)(void *)) _eglDestroyThreadInfo);
}
@@ -114,7 +172,6 @@ _eglInitCurrent(void)
void
_eglFiniCurrent(void)
{
- /* TODO trace and release all threads... */
_eglFiniTSD();
}