Merge branch 'for-master'
[profile/ivi/pixman.git] / pixman / pixman-compiler.h
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 #ifndef INT16_MIN
22 # define INT16_MIN              (-32767-1)
23 #endif
24
25 #ifndef INT16_MAX
26 # define INT16_MAX              (32767)
27 #endif
28
29 #ifndef INT32_MIN
30 # define INT32_MIN              (-2147483647-1)
31 #endif
32
33 #ifndef INT32_MAX
34 # define INT32_MAX              (2147483647)
35 #endif
36
37 #ifndef UINT32_MIN
38 # define UINT32_MIN             (0)
39 #endif
40
41 #ifndef UINT32_MAX
42 # define UINT32_MAX             (4294967295U)
43 #endif
44
45 #ifndef M_PI
46 # define M_PI                   3.14159265358979323846
47 #endif
48
49 #ifdef _MSC_VER
50 /* 'inline' is available only in C++ in MSVC */
51 #   define inline __inline
52 #   define force_inline __forceinline
53 #elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
54 #   define inline __inline__
55 #   define force_inline __inline__ __attribute__ ((__always_inline__))
56 #else
57 #   ifndef force_inline
58 #      define force_inline inline
59 #   endif
60 #endif
61
62 /* GCC visibility */
63 #if defined(__GNUC__) && __GNUC__ >= 4
64 #   define PIXMAN_EXPORT __attribute__ ((visibility("default")))
65 /* Sun Studio 8 visibility */
66 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
67 #   define PIXMAN_EXPORT __global
68 #else
69 #   define PIXMAN_EXPORT
70 #endif
71
72 /* TLS */
73 #if defined(PIXMAN_NO_TLS)
74
75 #   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)            \
76     static type name
77 #   define PIXMAN_GET_THREAD_LOCAL(name)                \
78     (&name)
79
80 #elif defined(TOOLCHAIN_SUPPORTS__THREAD)
81
82 #   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)                       \
83     static __thread type name
84 #   define PIXMAN_GET_THREAD_LOCAL(name)                                \
85     (&name)
86
87 #elif defined(__MINGW32__) && !defined(__WIN64)
88
89 /* We can't include <windows.h> as it causes carious clashes with
90  * identifiers in pixman, sigh. So just declare the functions we need
91  * here.
92  */
93 extern __stdcall long InterlockedCompareExchange(long volatile *, long, long);
94 #define InterlockedCompareExchangePointer(d,e,c)                        \
95     (void *)InterlockedCompareExchange((long volatile *)(d),(long)(e),(long)(c))
96 extern __stdcall int TlsAlloc (void);
97 extern __stdcall void *TlsGetValue (unsigned);
98 extern __stdcall int TlsSetValue (unsigned, void *);
99 extern __stdcall void *CreateMutexA(void *, int, char *);
100 extern __stdcall int CloseHandle(void *);
101 extern __stdcall unsigned WaitForSingleObject (void *, unsigned);
102 extern __stdcall int ReleaseMutex (void *);
103
104 #   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)                       \
105     static volatile int tls_ ## name ## _initialized = 0;               \
106     static void *tls_ ## name ## _mutex = NULL;                         \
107     static unsigned tls_ ## name ## _index;                             \
108                                                                         \
109     static type *                                                       \
110     tls_ ## name ## _alloc (void)                                       \
111     {                                                                   \
112         type *value = calloc (1, sizeof (type));                        \
113         if (value)                                                      \
114             TlsSetValue (tls_ ## name ## _index, value);                \
115         return value;                                                   \
116     }                                                                   \
117                                                                         \
118     static force_inline type *                                          \
119     tls_ ## name ## _get (void)                                         \
120     {                                                                   \
121         type *value;                                                    \
122         if (!tls_ ## name ## _initialized)                              \
123         {                                                               \
124             if (!tls_ ## name ## _mutex)                                \
125             {                                                           \
126                 void *mutex = CreateMutexA (NULL, 0, NULL);             \
127                 if (InterlockedCompareExchangePointer (                 \
128                         &tls_ ## name ## _mutex, mutex, NULL) != NULL)  \
129                 {                                                       \
130                     CloseHandle (mutex);                                \
131                 }                                                       \
132             }                                                           \
133             WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF);   \
134             if (!tls_ ## name ## _initialized)                          \
135             {                                                           \
136                 tls_ ## name ## _index = TlsAlloc ();                   \
137                 tls_ ## name ## _initialized = 1;                       \
138             }                                                           \
139             ReleaseMutex (tls_ ## name ## _mutex);                      \
140         }                                                               \
141         if (tls_ ## name ## _index == 0xFFFFFFFF)                       \
142             return NULL;                                                \
143         value = TlsGetValue (tls_ ## name ## _index);                   \
144         if (!value)                                                     \
145             value = tls_ ## name ## _alloc ();                          \
146         return value;                                                   \
147     }
148
149 #   define PIXMAN_GET_THREAD_LOCAL(name)                                \
150     tls_ ## name ## _get ()
151
152 #elif defined(_MSC_VER)
153
154 #   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)                       \
155     static __declspec(thread) type name
156 #   define PIXMAN_GET_THREAD_LOCAL(name)                                \
157     (&name)
158
159 #elif defined(HAVE_PTHREAD_SETSPECIFIC)
160
161 #include <pthread.h>
162
163 #  define PIXMAN_DEFINE_THREAD_LOCAL(type, name)                        \
164     static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \
165     static pthread_key_t tls_ ## name ## _key;                          \
166                                                                         \
167     static void                                                         \
168     tls_ ## name ## _make_key (void)                                    \
169     {                                                                   \
170         pthread_key_create (&tls_ ## name ## _key, NULL);               \
171     }                                                                   \
172                                                                         \
173     static type *                                                       \
174     tls_ ## name ## _alloc (void)                                       \
175     {                                                                   \
176         type *value = calloc (1, sizeof (type));                        \
177         if (value)                                                      \
178             pthread_setspecific (tls_ ## name ## _key, value);          \
179         return value;                                                   \
180     }                                                                   \
181                                                                         \
182     static force_inline type *                                          \
183     tls_ ## name ## _get (void)                                         \
184     {                                                                   \
185         type *value = NULL;                                             \
186         if (pthread_once (&tls_ ## name ## _once_control,               \
187                           tls_ ## name ## _make_key) == 0)              \
188         {                                                               \
189             value = pthread_getspecific (tls_ ## name ## _key);         \
190             if (!value)                                                 \
191                 value = tls_ ## name ## _alloc ();                      \
192         }                                                               \
193         return value;                                                   \
194     }
195
196 #   define PIXMAN_GET_THREAD_LOCAL(name)                                \
197     tls_ ## name ## _get ()
198
199 #else
200
201 #    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."
202
203 #endif