diff options
author | Chia-I Wu <olvaffe@gmail.com> | 2009-08-10 12:20:31 +0800 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2009-08-11 22:14:35 -0600 |
commit | f6c2f5e37925abe3ea7036b7a3bd6ca1721e4f73 (patch) | |
tree | 665e49ffb7235272024e3a3f1de3051183b96e17 /src/egl/main/eglcurrent.c | |
parent | e79d21ca1f11e5b584db0930eb0cf49869b0e77d (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.c | 89 |
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(); } |