1 /* Pixman uses some non-standard compiler features. This file ensures 2 * they exist 3 * 4 * The features are: 5 * 6 * FUNC must be defined to expand to the current function 7 * PIXMAN_EXPORT should be defined to whatever is required to 8 * export functions from a shared library 9 * limits limits for various types must be defined 10 * inline must be defined 11 * force_inline must be defined 12 */ 13 #if defined (__GNUC__) 14 # define FUNC ((const char*) (__PRETTY_FUNCTION__)) 15 #elif defined (__sun) || (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) 16 # define FUNC ((const char*) (__func__)) 17 #else 18 # define FUNC ((const char*) ("???")) 19 #endif 20 21 #if defined (__GNUC__) 22 # define unlikely(expr) __builtin_expect ((expr), 0) 23 #else 24 # define unlikely(expr) (expr) 25 #endif 26 27 #if defined (__GNUC__) 28 # define MAYBE_UNUSED __attribute__((unused)) 29 #else 30 # define MAYBE_UNUSED 31 #endif 32 33 #ifndef INT16_MIN 34 # define INT16_MIN (-32767-1) 35 #endif 36 37 #ifndef INT16_MAX 38 # define INT16_MAX (32767) 39 #endif 40 41 #ifndef INT32_MIN 42 # define INT32_MIN (-2147483647-1) 43 #endif 44 45 #ifndef INT32_MAX 46 # define INT32_MAX (2147483647) 47 #endif 48 49 #ifndef UINT32_MIN 50 # define UINT32_MIN (0) 51 #endif 52 53 #ifndef UINT32_MAX 54 # define UINT32_MAX (4294967295U) 55 #endif 56 57 #ifndef INT64_MIN 58 # define INT64_MIN (-9223372036854775807-1) 59 #endif 60 61 #ifndef INT64_MAX 62 # define INT64_MAX (9223372036854775807) 63 #endif 64 65 #ifndef SIZE_MAX 66 # define SIZE_MAX ((size_t)-1) 67 #endif 68 69 70 #ifndef M_PI 71 # define M_PI 3.14159265358979323846 72 #endif 73 74 #ifdef _MSC_VER 75 /* 'inline' is available only in C++ in MSVC */ 76 # define inline __inline 77 # define force_inline __forceinline 78 # define noinline __declspec(noinline) 79 #elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 80 # define inline __inline__ 81 # define force_inline __inline__ __attribute__ ((__always_inline__)) 82 # define noinline __attribute__((noinline)) 83 #else 84 # ifndef force_inline 85 # define force_inline inline 86 # endif 87 # ifndef noinline 88 # define noinline 89 # endif 90 #endif 91 92 /* GCC visibility */ 93 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32) 94 # define PIXMAN_EXPORT __attribute__ ((visibility("default"))) 95 /* Sun Studio 8 visibility */ 96 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) 97 # define PIXMAN_EXPORT __global 98 #else 99 # define PIXMAN_EXPORT 100 #endif 101 102 /* member offsets */ 103 #define CONTAINER_OF(type, member, data) \ 104 ((type *)(((uint8_t *)data) - offsetof (type, member))) 105 106 /* TLS */ 107 #if defined(PIXMAN_NO_TLS) 108 109 # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ 110 static type name 111 # define PIXMAN_GET_THREAD_LOCAL(name) \ 112 (&name) 113 114 #elif defined(TLS) 115 116 # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ 117 static TLS type name 118 # define PIXMAN_GET_THREAD_LOCAL(name) \ 119 (&name) 120 121 #elif defined(__MINGW32__) 122 123 # define _NO_W32_PSEUDO_MODIFIERS 124 # include <windows.h> 125 126 # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ 127 static volatile int tls_ ## name ## _initialized = 0; \ 128 static void *tls_ ## name ## _mutex = NULL; \ 129 static unsigned tls_ ## name ## _index; \ 130 \ 131 static type * \ 132 tls_ ## name ## _alloc (void) \ 133 { \ 134 type *value = calloc (1, sizeof (type)); \ 135 if (value) \ 136 TlsSetValue (tls_ ## name ## _index, value); \ 137 return value; \ 138 } \ 139 \ 140 static force_inline type * \ 141 tls_ ## name ## _get (void) \ 142 { \ 143 type *value; \ 144 if (!tls_ ## name ## _initialized) \ 145 { \ 146 if (!tls_ ## name ## _mutex) \ 147 { \ 148 void *mutex = CreateMutexA (NULL, 0, NULL); \ 149 if (InterlockedCompareExchangePointer ( \ 150 &tls_ ## name ## _mutex, mutex, NULL) != NULL) \ 151 { \ 152 CloseHandle (mutex); \ 153 } \ 154 } \ 155 WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF); \ 156 if (!tls_ ## name ## _initialized) \ 157 { \ 158 tls_ ## name ## _index = TlsAlloc (); \ 159 tls_ ## name ## _initialized = 1; \ 160 } \ 161 ReleaseMutex (tls_ ## name ## _mutex); \ 162 } \ 163 if (tls_ ## name ## _index == 0xFFFFFFFF) \ 164 return NULL; \ 165 value = TlsGetValue (tls_ ## name ## _index); \ 166 if (!value) \ 167 value = tls_ ## name ## _alloc (); \ 168 return value; \ 169 } 170 171 # define PIXMAN_GET_THREAD_LOCAL(name) \ 172 tls_ ## name ## _get () 173 174 #elif defined(_MSC_VER) 175 176 # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ 177 static __declspec(thread) type name 178 # define PIXMAN_GET_THREAD_LOCAL(name) \ 179 (&name) 180 181 #elif defined(HAVE_PTHREAD_SETSPECIFIC) 182 183 #include <pthread.h> 184 185 # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ 186 static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \ 187 static pthread_key_t tls_ ## name ## _key; \ 188 \ 189 static void \ 190 tls_ ## name ## _destroy_value (void *value) \ 191 { \ 192 free (value); \ 193 } \ 194 \ 195 static void \ 196 tls_ ## name ## _make_key (void) \ 197 { \ 198 pthread_key_create (&tls_ ## name ## _key, \ 199 tls_ ## name ## _destroy_value); \ 200 } \ 201 \ 202 static type * \ 203 tls_ ## name ## _alloc (void) \ 204 { \ 205 type *value = calloc (1, sizeof (type)); \ 206 if (value) \ 207 pthread_setspecific (tls_ ## name ## _key, value); \ 208 return value; \ 209 } \ 210 \ 211 static force_inline type * \ 212 tls_ ## name ## _get (void) \ 213 { \ 214 type *value = NULL; \ 215 if (pthread_once (&tls_ ## name ## _once_control, \ 216 tls_ ## name ## _make_key) == 0) \ 217 { \ 218 value = pthread_getspecific (tls_ ## name ## _key); \ 219 if (!value) \ 220 value = tls_ ## name ## _alloc (); \ 221 } \ 222 return value; \ 223 } 224 225 # define PIXMAN_GET_THREAD_LOCAL(name) \ 226 tls_ ## name ## _get () 227 228 #else 229 230 # error "Unknown thread local support for this system. Pixman will not work with multiple threads. Define PIXMAN_NO_TLS to acknowledge and accept this limitation and compile pixman without thread-safety support." 231 232 #endif 233