11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* Pixman uses some non-standard compiler features. This file ensures
21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * they exist
31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The features are:
51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    FUNC	     must be defined to expand to the current function
71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    PIXMAN_EXPORT  should be defined to whatever is required to
81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *                   export functions from a shared library
91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    limits	     limits for various types must be defined
101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    inline         must be defined
111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    force_inline   must be defined
121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined (__GNUC__)
141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define FUNC     ((const char*) (__PRETTY_FUNCTION__))
151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined (__sun) || (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define FUNC     ((const char*) (__func__))
171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define FUNC     ((const char*) ("???"))
191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined (__GNUC__)
221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define unlikely(expr) __builtin_expect ((expr), 0)
231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define unlikely(expr)  (expr)
251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined (__GNUC__)
281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define MAYBE_UNUSED  __attribute__((unused))
291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define MAYBE_UNUSED
311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef INT16_MIN
341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define INT16_MIN              (-32767-1)
351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef INT16_MAX
381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define INT16_MAX              (32767)
391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef INT32_MIN
421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define INT32_MIN              (-2147483647-1)
431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef INT32_MAX
461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define INT32_MAX              (2147483647)
471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef UINT32_MIN
501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define UINT32_MIN             (0)
511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef UINT32_MAX
541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define UINT32_MAX             (4294967295U)
551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef INT64_MIN
581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define INT64_MIN              (-9223372036854775807-1)
591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef INT64_MAX
621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define INT64_MAX              (9223372036854775807)
631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef SIZE_MAX
661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define SIZE_MAX               ((size_t)-1)
671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef M_PI
711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck# define M_PI			3.14159265358979323846
721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef _MSC_VER
751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 'inline' is available only in C++ in MSVC */
761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define inline __inline
771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define force_inline __forceinline
781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define noinline __declspec(noinline)
791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define inline __inline__
811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define force_inline __inline__ __attribute__ ((__always_inline__))
821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define noinline __attribute__((noinline))
831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   ifndef force_inline
851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#      define force_inline inline
861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   endif
871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   ifndef noinline
881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#      define noinline
891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   endif
901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* GCC visibility */
931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32)
941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_EXPORT __attribute__ ((visibility("default")))
951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* Sun Studio 8 visibility */
961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_EXPORT __global
981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_EXPORT
1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* member offsets */
1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define CONTAINER_OF(type, member, data)				\
1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    ((type *)(((uint8_t *)data) - offsetof (type, member)))
1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* TLS */
1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined(PIXMAN_NO_TLS)
1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)			\
1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static type name
1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_GET_THREAD_LOCAL(name)				\
1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (&name)
1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined(TLS)
1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)			\
1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static TLS type name
1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_GET_THREAD_LOCAL(name)				\
1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (&name)
1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined(__MINGW32__)
1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define _NO_W32_PSEUDO_MODIFIERS
1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   include <windows.h>
1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)			\
1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static volatile int tls_ ## name ## _initialized = 0;		\
1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static void *tls_ ## name ## _mutex = NULL;				\
1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static unsigned tls_ ## name ## _index;				\
1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static type *							\
1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _alloc (void)					\
1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        type *value = calloc (1, sizeof (type));			\
1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (value)							\
1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            TlsSetValue (tls_ ## name ## _index, value);		\
1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        return value;							\
1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }									\
1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static force_inline type *						\
1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _get (void)						\
1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	type *value;							\
1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!tls_ ## name ## _initialized)				\
1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{								\
1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (!tls_ ## name ## _mutex)				\
1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {								\
1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		void *mutex = CreateMutexA (NULL, 0, NULL);		\
1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		if (InterlockedCompareExchangePointer (			\
1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			&tls_ ## name ## _mutex, mutex, NULL) != NULL)	\
1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		{							\
1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    CloseHandle (mutex);				\
1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}							\
1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }								\
1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF);	\
1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (!tls_ ## name ## _initialized)				\
1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {								\
1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		tls_ ## name ## _index = TlsAlloc ();			\
1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		tls_ ## name ## _initialized = 1;			\
1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }								\
1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    ReleaseMutex (tls_ ## name ## _mutex);			\
1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}								\
1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (tls_ ## name ## _index == 0xFFFFFFFF)			\
1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    return NULL;						\
1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	value = TlsGetValue (tls_ ## name ## _index);			\
1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (!value)							\
1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    value = tls_ ## name ## _alloc ();				\
1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return value;							\
1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_GET_THREAD_LOCAL(name)				\
1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _get ()
1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined(_MSC_VER)
1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_DEFINE_THREAD_LOCAL(type, name)			\
1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static __declspec(thread) type name
1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_GET_THREAD_LOCAL(name)				\
1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    (&name)
1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#elif defined(HAVE_PTHREAD_SETSPECIFIC)
1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <pthread.h>
1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#  define PIXMAN_DEFINE_THREAD_LOCAL(type, name)			\
1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \
1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static pthread_key_t tls_ ## name ## _key;				\
1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static void								\
1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _destroy_value (void *value)			\
1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	free (value);							\
1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }									\
1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static void								\
1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _make_key (void)					\
1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pthread_key_create (&tls_ ## name ## _key,			\
1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    tls_ ## name ## _destroy_value);		\
2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }									\
2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static type *							\
2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _alloc (void)					\
2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	type *value = calloc (1, sizeof (type));			\
2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (value)							\
2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    pthread_setspecific (tls_ ## name ## _key, value);		\
2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return value;							\
2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }									\
2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck									\
2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static force_inline type *						\
2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _get (void)						\
2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {									\
2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	type *value = NULL;						\
2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pthread_once (&tls_ ## name ## _once_control,		\
2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  tls_ ## name ## _make_key) == 0)		\
2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{								\
2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    value = pthread_getspecific (tls_ ## name ## _key);		\
2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (!value)							\
2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		value = tls_ ## name ## _alloc ();			\
2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}								\
2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	return value;							\
2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#   define PIXMAN_GET_THREAD_LOCAL(name)				\
2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    tls_ ## name ## _get ()
2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#    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."
2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
233