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