build: Rename sources.mak -> Makefile.sources
[mesa.git] / src / mapi / mapi / u_thread.h
index 4405ec9c509f045afd4fea2c52839c2adb4ac5c7..a5e5043701f638341ad31eacab43e6ecb4d613a3 100644 (file)
 #ifndef _U_THREAD_H_
 #define _U_THREAD_H_
 
+#include <stdio.h>
+#include <stdlib.h>
 #include "u_compiler.h"
 
-#if defined(PTHREADS) || defined(WIN32)
+#if defined(HAVE_PTHREAD)
+#include <pthread.h> /* POSIX threads headers */
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#if defined(HAVE_PTHREAD) || defined(_WIN32)
 #ifndef THREADS
 #define THREADS
 #endif
 #endif
 
+/*
+ * 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 /*
  * POSIX threads. This should be your choice in the Unix world
  * whenever possible.  When building with POSIX threads, be sure
  * compiler flag.  On Solaris with gcc, use -D_REENTRANT to enable
  * proper compiling for MT-safe libc etc.
  */
-#if defined(PTHREADS)
-#include <pthread.h> /* POSIX threads headers */
+#if defined(HAVE_PTHREAD)
 
 struct u_tsd {
    pthread_key_t key;
-   int initMagic;
+   unsigned initMagic;
 };
 
 typedef pthread_mutex_t u_mutex;
@@ -77,7 +105,47 @@ typedef pthread_mutex_t u_mutex;
 #define u_mutex_lock(name)    (void) pthread_mutex_lock(&(name))
 #define u_mutex_unlock(name)  (void) pthread_mutex_unlock(&(name))
 
-#endif /* PTHREADS */
+static INLINE unsigned long
+u_thread_self(void)
+{
+   return (unsigned long) pthread_self();
+}
+
+
+static INLINE 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;
+}
+
+
+static INLINE void *
+u_tsd_get(struct u_tsd *tsd)
+{
+   if (tsd->initMagic != INIT_MAGIC) {
+      u_tsd_init(tsd);
+   }
+   return pthread_getspecific(tsd->key);
+}
+
+
+static INLINE void
+u_tsd_set(struct u_tsd *tsd, void *ptr)
+{
+   if (tsd->initMagic != INIT_MAGIC) {
+      u_tsd_init(tsd);
+   }
+   if (pthread_setspecific(tsd->key, ptr) != 0) {
+      perror(SET_TSD_ERROR);
+      exit(-1);
+   }
+}
+
+#endif /* HAVE_PTHREAD */
 
 
 /*
@@ -85,12 +153,11 @@ typedef pthread_mutex_t u_mutex;
  * IMPORTANT: Link with multithreaded runtime library when THREADS are
  * used!
  */
-#ifdef WIN32
-#include <windows.h>
+#ifdef _WIN32
 
 struct u_tsd {
    DWORD key;
-   int   initMagic;
+   unsigned initMagic;
 };
 
 typedef CRITICAL_SECTION u_mutex;
@@ -104,7 +171,61 @@ typedef CRITICAL_SECTION u_mutex;
 #define u_mutex_lock(name)    EnterCriticalSection(&name)
 #define u_mutex_unlock(name)  LeaveCriticalSection(&name)
 
-#endif /* WIN32 */
+static INLINE unsigned long
+u_thread_self(void)
+{
+   return GetCurrentThreadId();
+}
+
+
+static INLINE void
+u_tsd_init(struct u_tsd *tsd)
+{
+   tsd->key = TlsAlloc();
+   if (tsd->key == TLS_OUT_OF_INDEXES) {
+      perror(INIT_TSD_ERROR);
+      exit(-1);
+   }
+   tsd->initMagic = INIT_MAGIC;
+}
+
+
+static INLINE void
+u_tsd_destroy(struct u_tsd *tsd)
+{
+   if (tsd->initMagic != INIT_MAGIC) {
+      return;
+   }
+   TlsFree(tsd->key);
+   tsd->initMagic = 0x0;
+}
+
+
+static INLINE void *
+u_tsd_get(struct u_tsd *tsd)
+{
+   if (tsd->initMagic != INIT_MAGIC) {
+      u_tsd_init(tsd);
+   }
+   return TlsGetValue(tsd->key);
+}
+
+
+static INLINE 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);
+      exit(-1);
+   }
+}
+
+#endif /* _WIN32 */
 
 
 /*
@@ -113,7 +234,7 @@ typedef CRITICAL_SECTION u_mutex;
 #ifndef THREADS
 
 struct u_tsd {
-   int initMagic; 
+   unsigned initMagic;
 };
 
 typedef unsigned u_mutex;
@@ -124,22 +245,43 @@ typedef unsigned u_mutex;
 #define u_mutex_lock(name)             (void) name
 #define u_mutex_unlock(name)           (void) name
 
-#endif /* THREADS */
+/*
+ * no-op functions
+ */
+
+static INLINE unsigned long
+u_thread_self(void)
+{
+   return 0;
+}
+
 
+static INLINE void
+u_tsd_init(struct u_tsd *tsd)
+{
+   (void) tsd;
+}
 
-unsigned long
-u_thread_self(void);
 
-void
-u_tsd_init(struct u_tsd *tsd);
+static INLINE void *
+u_tsd_get(struct u_tsd *tsd)
+{
+   (void) tsd;
+   return NULL;
+}
 
-void
-u_tsd_destroy(struct u_tsd *tsd); /* WIN32 only */
 
-void *
-u_tsd_get(struct u_tsd *tsd);
+static INLINE void
+u_tsd_set(struct u_tsd *tsd, void *ptr)
+{
+   (void) tsd;
+   (void) ptr;
+}
+#endif /* THREADS */
+
 
-void
-u_tsd_set(struct u_tsd *tsd, void *ptr);
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* _U_THREAD_H_ */