From a73c6540d9a7f6e26d8568ba2fc522cb865f0a6c Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 23 Apr 2010 16:06:26 +0800 Subject: mapi: Add mapi and share the code with glapi. Specifically, move all or most of glapi/glapi.c to mapi/u_current.c, glapi/glapi_execmem.c to mapi/u_execmem.c, glapi/glthread.[ch] to mapi/u_thread.[ch] and remove their dependencies on core Mesa headers. --- src/mapi/mapi/sources.mak | 6 + src/mapi/mapi/u_compiler.h | 48 ++++++++ src/mapi/mapi/u_current.c | 274 +++++++++++++++++++++++++++++++++++++++++++++ src/mapi/mapi/u_current.h | 93 +++++++++++++++ src/mapi/mapi/u_execmem.c | 122 ++++++++++++++++++++ src/mapi/mapi/u_execmem.h | 7 ++ src/mapi/mapi/u_thread.c | 254 +++++++++++++++++++++++++++++++++++++++++ src/mapi/mapi/u_thread.h | 200 +++++++++++++++++++++++++++++++++ 8 files changed, 1004 insertions(+) create mode 100644 src/mapi/mapi/sources.mak create mode 100644 src/mapi/mapi/u_compiler.h create mode 100644 src/mapi/mapi/u_current.c create mode 100644 src/mapi/mapi/u_current.h create mode 100644 src/mapi/mapi/u_execmem.c create mode 100644 src/mapi/mapi/u_execmem.h create mode 100644 src/mapi/mapi/u_thread.c create mode 100644 src/mapi/mapi/u_thread.h (limited to 'src/mapi/mapi') diff --git a/src/mapi/mapi/sources.mak b/src/mapi/mapi/sources.mak new file mode 100644 index 0000000000..9e27f45e2a --- /dev/null +++ b/src/mapi/mapi/sources.mak @@ -0,0 +1,6 @@ +# src/mapi/mapi/sources.mak + +MAPI_GLAPI_SOURCES = \ + u_current.c \ + u_execmem.c \ + u_thread.c diff --git a/src/mapi/mapi/u_compiler.h b/src/mapi/mapi/u_compiler.h new file mode 100644 index 0000000000..cc9e2cd1e8 --- /dev/null +++ b/src/mapi/mapi/u_compiler.h @@ -0,0 +1,48 @@ +#ifndef _U_COMPILER_H_ +#define _U_COMPILER_H_ + +/* Function inlining */ +#ifndef INLINE +# ifdef __cplusplus +# define INLINE inline +# elif defined(__GNUC__) +# define INLINE __inline__ +# elif defined(_MSC_VER) +# define INLINE __inline +# elif defined(__ICL) +# define INLINE __inline +# elif defined(__INTEL_COMPILER) +# define INLINE inline +# elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100) +# define INLINE __inline +# elif defined(__SUNPRO_C) && defined(__C99FEATURES__) +# define INLINE inline +# elif (__STDC_VERSION__ >= 199901L) /* C99 */ +# define INLINE inline +# else +# define INLINE +# endif +#endif + +/* Function visibility */ +#ifndef PUBLIC +# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +# define PUBLIC __attribute__((visibility("default"))) +# define HIDDEN __attribute__((visibility("hidden"))) +# else +# define PUBLIC +# define HIDDEN +# endif +#endif + +#ifndef likely +# if defined(__GNUC__) +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif +#endif + +#endif /* _U_COMPILER_H_ */ diff --git a/src/mapi/mapi/u_current.c b/src/mapi/mapi/u_current.c new file mode 100644 index 0000000000..91547c4830 --- /dev/null +++ b/src/mapi/mapi/u_current.c @@ -0,0 +1,274 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * This file manages the OpenGL API dispatch layer. + * The dispatch table (struct _glapi_table) is basically just a list + * of function pointers. + * There are functions to set/get the current dispatch table for the + * current thread and to manage registration/dispatch of dynamically + * added extension functions. + * + * It's intended that this file and the other glapi*.[ch] files are + * flexible enough to be reused in several places: XFree86, DRI- + * based libGL.so, and perhaps the SGI SI. + * + * NOTE: There are no dependencies on Mesa in this code. + * + * Versions (API changes): + * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0 + * 2001/01/16 - added dispatch override feature for Mesa 3.5 + * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1. + * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints + * itself (using offset ~0). _glapi_add_entrypoint() can be + * called afterward and it'll fill in the correct dispatch + * offset. This allows DRI libGL to avoid probing for DRI + * drivers! No changes to the public glapi interface. + */ + +#include "u_current.h" +#include "u_thread.h" + +#ifndef MAPI_GLAPI_CURRENT + +#include "table.h" +#include "stub.h" + +#else + +extern void init_glapi_relocs_once(void); +extern void (*__glapi_noop_table[])(void); + +#define table_noop_array __glapi_noop_table +#define stub_init_once() init_glapi_relocs_once() + +#endif + +/** + * \name Current dispatch and current context control variables + * + * Depending on whether or not multithreading is support, and the type of + * support available, several variables are used to store the current context + * pointer and the current dispatch table pointer. In the non-threaded case, + * the variables \c _glapi_Dispatch and \c _glapi_Context are used for this + * purpose. + * + * In the "normal" threaded case, the variables \c _glapi_Dispatch and + * \c _glapi_Context will be \c NULL if an application is detected as being + * multithreaded. Single-threaded applications will use \c _glapi_Dispatch + * and \c _glapi_Context just like the case without any threading support. + * When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state + * data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the + * static dispatch functions access these variables via \c _glapi_get_dispatch + * and \c _glapi_get_context. + * + * 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. + * + * 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 + * \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and + * \c _glapi_Context be hardcoded to \c NULL maintains binary compatability + * between TLS enabled loaders and non-TLS DRI drivers. + */ +/*@{*/ +#if defined(GLX_USE_TLS) + +__thread struct _glapi_table *_glapi_tls_Dispatch + __attribute__((tls_model("initial-exec"))) + = (struct _glapi_table *) table_noop_array; + +__thread void * _glapi_tls_Context + __attribute__((tls_model("initial-exec"))); + +const struct _glapi_table *_glapi_Dispatch; +const void *_glapi_Context; + +#else + +struct _glapi_table *_glapi_Dispatch = + (struct _glapi_table *) table_noop_array; +void *_glapi_Context; + +#ifdef THREADS +struct u_tsd _gl_DispatchTSD; +static struct u_tsd ContextTSD; +static int ThreadSafe; +#endif /* THREADS */ + +#endif /* defined(GLX_USE_TLS) */ +/*@}*/ + + +void +_glapi_destroy_multithread(void) +{ +#if defined(THREADS) && defined(WIN32_THREADS) + u_tsd_destroy(&_gl_DispatchTSD); + u_tsd_destroy(&ContextTSD); +#endif +} + + +#if defined(THREADS) && !defined(GLX_USE_TLS) + +static void +_glapi_init_multithread(void) +{ + u_tsd_init(&_gl_DispatchTSD); + u_tsd_init(&ContextTSD); +} + +/** + * Mutex for multithread check. + */ +#ifdef WIN32_THREADS +/* _glthread_DECLARE_STATIC_MUTEX is broken on windows. There will be race! */ +#define CHECK_MULTITHREAD_LOCK() +#define CHECK_MULTITHREAD_UNLOCK() +#else +u_mutex_declare_static(ThreadCheckMutex); +#define CHECK_MULTITHREAD_LOCK() u_mutex_lock(ThreadCheckMutex) +#define CHECK_MULTITHREAD_UNLOCK() u_mutex_unlock(ThreadCheckMutex) +#endif + +/** + * We should call this periodically from a function such as glXMakeCurrent + * in order to test if multiple threads are being used. + */ +void +_glapi_check_multithread(void) +{ + static unsigned long knownID; + static int firstCall = 1; + + if (ThreadSafe) + return; + + CHECK_MULTITHREAD_LOCK(); + if (firstCall) { + _glapi_init_multithread(); + + knownID = u_thread_self(); + firstCall = 0; + } + else if (knownID != u_thread_self()) { + ThreadSafe = 1; + _glapi_set_dispatch(NULL); + _glapi_set_context(NULL); + } + CHECK_MULTITHREAD_UNLOCK(); +} + +#else + +void +_glapi_check_multithread(void) +{ +} + +#endif + + + +/** + * Set the current context pointer for this thread. + * The context pointer is an opaque type which should be cast to + * void from the real context pointer type. + */ +void +_glapi_set_context(void *context) +{ +#if defined(GLX_USE_TLS) + _glapi_tls_Context = context; +#elif defined(THREADS) + u_tsd_set(&ContextTSD, context); + _glapi_Context = (ThreadSafe) ? NULL : context; +#else + _glapi_Context = context; +#endif +} + +/** + * Get the current context pointer for this thread. + * The context pointer is an opaque type which should be cast from + * void to the real context pointer type. + */ +void * +_glapi_get_context(void) +{ +#if defined(GLX_USE_TLS) + return _glapi_tls_Context; +#elif defined(THREADS) + return (ThreadSafe) + ? u_tsd_get(&ContextTSD) + : _glapi_Context; +#else + return _glapi_Context; +#endif +} + +/** + * Set the global or per-thread dispatch table pointer. + * If the dispatch parameter is NULL we'll plug in the no-op dispatch + * table (__glapi_noop_table). + */ +void +_glapi_set_dispatch(struct _glapi_table *dispatch) +{ + stub_init_once(); + + if (!dispatch) + dispatch = (struct _glapi_table *) table_noop_array; + +#if defined(GLX_USE_TLS) + _glapi_tls_Dispatch = dispatch; +#elif defined(THREADS) + u_tsd_set(&_gl_DispatchTSD, (void *) dispatch); + _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch; +#else + _glapi_Dispatch = dispatch; +#endif +} + +/** + * Return pointer to current dispatch table for calling thread. + */ +struct _glapi_table * +_glapi_get_dispatch(void) +{ +#if defined(GLX_USE_TLS) + return _glapi_tls_Dispatch; +#elif defined(THREADS) + return (ThreadSafe) + ? (struct _glapi_table *) u_tsd_get(&_gl_DispatchTSD) + : _glapi_Dispatch; +#else + return _glapi_Dispatch; +#endif +} diff --git a/src/mapi/mapi/u_current.h b/src/mapi/mapi/u_current.h new file mode 100644 index 0000000000..a6256f5b51 --- /dev/null +++ b/src/mapi/mapi/u_current.h @@ -0,0 +1,93 @@ +#ifndef _U_CURRENT_H_ +#define _U_CURRENT_H_ + +#include "u_compiler.h" + +#ifdef MAPI_GLAPI_CURRENT +#define GLAPI_EXPORT PUBLIC +#else +#define GLAPI_EXPORT +#endif + +/* + * Unlike other utility functions, we need to keep the old names (_glapi_*) for + * ABI compatibility. The desired functions are wrappers to the old ones. + */ + +struct _glapi_table; + +#ifdef GLX_USE_TLS + +GLAPI_EXPORT extern __thread struct _glapi_table *_glapi_tls_Dispatch + __attribute__((tls_model("initial-exec"))); + +GLAPI_EXPORT extern __thread void *_glapi_tls_Context + __attribute__((tls_model("initial-exec"))); + +GLAPI_EXPORT extern const struct _glapi_table *_glapi_Dispatch; +GLAPI_EXPORT extern const void *_glapi_Context; + +#else /* GLX_USE_TLS */ + +GLAPI_EXPORT extern struct _glapi_table *_glapi_Dispatch; +GLAPI_EXPORT extern void *_glapi_Context; + +#endif /* GLX_USE_TLS */ + +GLAPI_EXPORT void +_glapi_check_multithread(void); + +GLAPI_EXPORT void +_glapi_set_context(void *context); + +GLAPI_EXPORT void * +_glapi_get_context(void); + +GLAPI_EXPORT void +_glapi_set_dispatch(struct _glapi_table *dispatch); + +GLAPI_EXPORT struct _glapi_table * +_glapi_get_dispatch(void); + +void +_glapi_destroy_multithread(void); + + +struct mapi_table; + +static INLINE void +u_current_set(const struct mapi_table *tbl) +{ + _glapi_check_multithread(); + _glapi_set_dispatch((struct _glapi_table *) tbl); +} + +static INLINE const struct mapi_table * +u_current_get(void) +{ +#ifdef GLX_USE_TLS + return (const struct mapi_table *) _glapi_tls_Dispatch; +#else + return (const struct mapi_table *) (likely(_glapi_Dispatch) ? + _glapi_Dispatch : _glapi_get_dispatch()); +#endif +} + +static INLINE void +u_current_set_user(void *ptr) +{ + _glapi_check_multithread(); + _glapi_set_context(ptr); +} + +static INLINE void * +u_current_get_user(void) +{ +#ifdef GLX_USE_TLS + return _glapi_tls_Context; +#else + return likely(_glapi_Context) ? _glapi_Context : _glapi_get_context(); +#endif +} + +#endif /* GLX_USE_TLS */ diff --git a/src/mapi/mapi/u_execmem.c b/src/mapi/mapi/u_execmem.c new file mode 100644 index 0000000000..0e0f8aa316 --- /dev/null +++ b/src/mapi/mapi/u_execmem.c @@ -0,0 +1,122 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file glapi_execmem.c + * + * Function for allocating executable memory for dispatch stubs. + * + * Copied from main/execmem.c and simplified for dispatch stubs. + */ + + +#include "u_compiler.h" +#include "u_thread.h" +#include "u_execmem.h" + + +#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun) + +#include +#include + +#ifdef MESA_SELINUX +#include +#endif + + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + + +#define EXEC_MAP_SIZE (4*1024) + +u_mutex_declare_static(exec_mutex); + +static unsigned int head = 0; + +static unsigned char *exec_mem = NULL; + + +/* + * Dispatch stubs are of fixed size and never freed. Thus, we do not need to + * overlay a heap, we just mmap a page and manage through an index. + */ + +static int +init_map(void) +{ +#ifdef MESA_SELINUX + if (is_selinux_enabled()) { + if (!security_get_boolean_active("allow_execmem") || + !security_get_boolean_pending("allow_execmem")) + return 0; + } +#endif + + if (!exec_mem) + exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + return (exec_mem != MAP_FAILED); +} + + +void * +u_execmem_alloc(unsigned int size) +{ + void *addr = NULL; + + u_mutex_lock(exec_mutex); + + if (!init_map()) + goto bail; + + /* free space check, assumes no integer overflow */ + if (head + size > EXEC_MAP_SIZE) + goto bail; + + /* allocation, assumes proper addr and size alignement */ + addr = exec_mem + head; + head += size; + +bail: + u_mutex_unlock(exec_mutex); + + return addr; +} + + +#else + +void * +u_execmem_alloc(unsigned int size) +{ + return malloc(size); +} + + +#endif diff --git a/src/mapi/mapi/u_execmem.h b/src/mapi/mapi/u_execmem.h new file mode 100644 index 0000000000..13fff8df22 --- /dev/null +++ b/src/mapi/mapi/u_execmem.h @@ -0,0 +1,7 @@ +#ifndef _U_EXECMEM_H_ +#define _U_EXECMEM_H_ + +void * +u_execmem_alloc(unsigned int size); + +#endif /* _U_EXECMEM_H_ */ diff --git a/src/mapi/mapi/u_thread.c b/src/mapi/mapi/u_thread.c new file mode 100644 index 0000000000..e0fa64ae03 --- /dev/null +++ b/src/mapi/mapi/u_thread.c @@ -0,0 +1,254 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include +#include +#include "u_compiler.h" +#include "u_thread.h" + + +/* + * This file should still compile even when THREADS is not defined. + * This is to make things easier to deal with on the makefile scene.. + */ +#ifdef THREADS +#include + +/* + * Error messages + */ +#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data" +#define GET_TSD_ERROR "_glthread_: failed to get thread specific data" +#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data" + + +/* + * Magic number to determine if a TSD object has been initialized. + * Kind of a hack but there doesn't appear to be a better cross-platform + * solution. + */ +#define INIT_MAGIC 0xff8adc98 + + + +/* + * POSIX Threads -- The best way to go if your platform supports them. + * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly + * has them, and many of the free Unixes now have them. + * Be sure to use appropriate -mt or -D_REENTRANT type + * compile flags when building. + */ +#ifdef PTHREADS + +unsigned long +u_thread_self(void) +{ + return (unsigned long) pthread_self(); +} + + +void +u_tsd_init(struct u_tsd *tsd) +{ + if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { + perror(INIT_TSD_ERROR); + exit(-1); + } + tsd->initMagic = INIT_MAGIC; +} + + +void * +u_tsd_get(struct u_tsd *tsd) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + return pthread_getspecific(tsd->key); +} + + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + if (pthread_setspecific(tsd->key, ptr) != 0) { + perror(SET_TSD_ERROR); + exit(-1); + } +} + +#endif /* PTHREADS */ + + + +/* + * Win32 Threads. The only available option for Windows 95/NT. + * Be sure that you compile using the Multithreaded runtime, otherwise + * bad things will happen. + */ +#ifdef WIN32_THREADS + +static void InsteadOf_exit(int nCode) +{ + DWORD dwErr = GetLastError(); +} + +unsigned long +u_thread_self(void) +{ + return GetCurrentThreadId(); +} + + +void +u_tsd_init(struct u_tsd *tsd) +{ + tsd->key = TlsAlloc(); + if (tsd->key == TLS_OUT_OF_INDEXES) { + perror(INIT_TSD_ERROR); + InsteadOf_exit(-1); + } + tsd->initMagic = INIT_MAGIC; +} + + +void +u_tsd_destroy(struct u_tsd *tsd) +{ + if (tsd->initMagic != INIT_MAGIC) { + return; + } + TlsFree(tsd->key); + tsd->initMagic = 0x0; +} + + +void * +u_tsd_get(struct u_tsd *tsd) +{ + if (tsd->initMagic != INIT_MAGIC) { + u_tsd_init(tsd); + } + return TlsGetValue(tsd->key); +} + + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + /* the following code assumes that the struct u_tsd has been initialized + to zero at creation */ + if (tsd->initMagic != INIT_MAGIC) { + u_tsd_init(tsd); + } + if (TlsSetValue(tsd->key, ptr) == 0) { + perror(SET_TSD_ERROR); + InsteadOf_exit(-1); + } +} + +#endif /* WIN32_THREADS */ + +/* + * BeOS threads + */ +#ifdef BEOS_THREADS + +unsigned long +u_thread_self(void) +{ + return (unsigned long) find_thread(NULL); +} + +void +u_tsd_init(struct u_tsd *tsd) +{ + tsd->key = tls_allocate(); + tsd->initMagic = INIT_MAGIC; +} + +void * +u_tsd_get(struct u_tsd *tsd) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + return tls_get(tsd->key); +} + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + tls_set(tsd->key, ptr); +} + +#endif /* BEOS_THREADS */ + + + +#else /* THREADS */ + + +/* + * no-op functions + */ + +unsigned long +_glthread_GetID(void) +{ + return 0; +} + + +void +u_tsd_init(struct u_tsd *tsd) +{ + (void) tsd; +} + + +void * +u_tsd_get(struct u_tsd *tsd) +{ + (void) tsd; + return NULL; +} + + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + (void) tsd; + (void) ptr; +} + + +#endif /* THREADS */ diff --git a/src/mapi/mapi/u_thread.h b/src/mapi/mapi/u_thread.h new file mode 100644 index 0000000000..992dbaace9 --- /dev/null +++ b/src/mapi/mapi/u_thread.h @@ -0,0 +1,200 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Thread support for gl dispatch. + * + * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu) + * and Christoph Poliwoda (poliwoda@volumegraphics.com) + * Revised by Keith Whitwell + * Adapted for new gl dispatcher by Brian Paul + * Modified for use in mapi by Chia-I Wu + */ + +/* + * If this file is accidentally included by a non-threaded build, + * it should not cause the build to fail, or otherwise cause problems. + * In general, it should only be included when needed however. + */ + +#ifndef _U_THREAD_H_ +#define _U_THREAD_H_ + +#include "u_compiler.h" + +#if defined(PTHREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS) +#ifndef THREADS +#define THREADS +#endif +#endif + +/* + * POSIX threads. This should be your choice in the Unix world + * whenever possible. When building with POSIX threads, be sure + * to enable any compiler flags which will cause the MT-safe + * libc (if one exists) to be used when linking, as well as any + * header macros for MT-safe errno, etc. For Solaris, this is the -mt + * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable + * proper compiling for MT-safe libc etc. + */ +#if defined(PTHREADS) +#include /* POSIX threads headers */ + +struct u_tsd { + pthread_key_t key; + int initMagic; +}; + +typedef pthread_mutex_t u_mutex; + +#define u_mutex_declare_static(name) \ + static u_mutex name = PTHREAD_MUTEX_INITIALIZER + +#define u_mutex_init(name) pthread_mutex_init(&(name), NULL) +#define u_mutex_destroy(name) pthread_mutex_destroy(&(name)) +#define u_mutex_lock(name) (void) pthread_mutex_lock(&(name)) +#define u_mutex_unlock(name) (void) pthread_mutex_unlock(&(name)) + +#endif /* PTHREADS */ + + +/* + * Windows threads. Should work with Windows NT and 95. + * IMPORTANT: Link with multithreaded runtime library when THREADS are + * used! + */ +#ifdef WIN32_THREADS +#include + +struct u_tsd { + DWORD key; + int initMagic; +}; + +typedef CRITICAL_SECTION u_mutex; + +#define u_mutex_declare_static(name) \ + /* static */ u_mutex name = { 0, 0, 0, 0, 0, 0 } + +#define u_mutex_init(name) InitializeCriticalSection(&name) +#define u_mutex_destroy(name) DeleteCriticalSection(&name) +#define u_mutex_lock(name) EnterCriticalSection(&name) +#define u_mutex_unlock(name) LeaveCriticalSection(&name) + +#endif /* WIN32_THREADS */ + + +/* + * BeOS threads. R5.x required. + */ +#ifdef BEOS_THREADS + +/* Problem with OS.h and this file on haiku */ +#ifndef __HAIKU__ +#include +#endif + +#include + +/* The only two typedefs required here + * this is cause of the OS.h problem + */ +#ifdef __HAIKU__ +typedef int32 thread_id; +typedef int32 sem_id; +#endif + +struct u_tsd { + int32 key; + int initMagic; +}; + +/* Use Benaphore, aka speeder semaphore */ +typedef struct { + int32 lock; + sem_id sem; +} benaphore; +typedef benaphore u_mutex; + +#define u_mutex_declare_static(name) \ + static u_mutex name = { 0, 0 } + +#define u_mutex_init(name) \ + name.sem = create_sem(0, #name"_benaphore"), \ + name.lock = 0 + +#define u_mutex_destroy(name) \ + delete_sem(name.sem), \ + name.lock = 0 + +#define u_mutex_lock(name) \ + if (name.sem == 0) \ + u_mutex_init(name); \ + if (atomic_add(&(name.lock), 1) >= 1) \ + acquire_sem(name.sem) + +#define u_mutex_unlock(name) \ + if (atomic_add(&(name.lock), -1) > 1) \ + release_sem(name.sem) + +#endif /* BEOS_THREADS */ + + +/* + * THREADS not defined + */ +#ifndef THREADS + +struct u_tsd { + int initMagic; +}; + +typedef unsigned u_mutex; + +#define u_mutex_declare_static(name) static u_mutex name = 0 +#define u_mutex_init(name) (void) name +#define u_mutex_destroy(name) (void) name +#define u_mutex_lock(name) (void) name +#define u_mutex_unlock(name) (void) name + +#endif /* THREADS */ + + +unsigned long +u_thread_self(void); + +void +u_tsd_init(struct u_tsd *tsd); + +void +u_tsd_destroy(struct u_tsd *tsd); /* WIN32 only */ + +void * +u_tsd_get(struct u_tsd *tsd); + +void +u_tsd_set(struct u_tsd *tsd, void *ptr); + +#endif /* _U_THREAD_H_ */ -- cgit v1.2.3