Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2007 Chris Wilson
  4.  * Copyright © 2010 Andrea Canciani
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it either under the terms of the GNU Lesser General Public
  8.  * License version 2.1 as published by the Free Software Foundation
  9.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  10.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  11.  * notice, a recipient may use your version of this file under either
  12.  * the MPL or the LGPL.
  13.  *
  14.  * You should have received a copy of the LGPL along with this library
  15.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  17.  * You should have received a copy of the MPL along with this library
  18.  * in the file COPYING-MPL-1.1
  19.  *
  20.  * The contents of this file are subject to the Mozilla Public License
  21.  * Version 1.1 (the "License"); you may not use this file except in
  22.  * compliance with the License. You may obtain a copy of the License at
  23.  * http://www.mozilla.org/MPL/
  24.  *
  25.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  26.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  27.  * the specific language governing rights and limitations.
  28.  *
  29.  * The Original Code is the cairo graphics library.
  30.  *
  31.  * The Initial Developer of the Original Code is University of Southern
  32.  * California.
  33.  *
  34.  * Contributor(s):
  35.  *      Chris Wilson <chris@chris-wilson.co.uk>
  36.  *      Andrea Canciani <ranma42@gmail.com>
  37.  */
  38.  
  39. #ifndef CAIRO_ATOMIC_PRIVATE_H
  40. #define CAIRO_ATOMIC_PRIVATE_H
  41.  
  42. # include "cairo-compiler-private.h"
  43.  
  44. #if HAVE_CONFIG_H
  45. #include "config.h"
  46. #endif
  47.  
  48. /* The autoconf on OpenBSD 4.5 produces the malformed constant name
  49.  * SIZEOF_VOID__ rather than SIZEOF_VOID_P.  Work around that here. */
  50. #if !defined(SIZEOF_VOID_P) && defined(SIZEOF_VOID__)
  51. # define SIZEOF_VOID_P SIZEOF_VOID__
  52. #endif
  53.  
  54. CAIRO_BEGIN_DECLS
  55.  
  56. #if HAVE_INTEL_ATOMIC_PRIMITIVES
  57.  
  58. #define HAS_ATOMIC_OPS 1
  59.  
  60. typedef int cairo_atomic_int_t;
  61.  
  62. #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
  63. static cairo_always_inline cairo_atomic_int_t
  64. _cairo_atomic_int_get (cairo_atomic_int_t *x)
  65. {
  66.     __sync_synchronize ();
  67.     return *x;
  68. }
  69.  
  70. static cairo_always_inline void *
  71. _cairo_atomic_ptr_get (void **x)
  72. {
  73.     __sync_synchronize ();
  74.     return *x;
  75. }
  76. #else
  77. # define _cairo_atomic_int_get(x) (*x)
  78. # define _cairo_atomic_ptr_get(x) (*x)
  79. #endif
  80.  
  81. # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
  82. # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
  83. # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
  84. # define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
  85.  
  86. #if SIZEOF_VOID_P==SIZEOF_INT
  87. typedef int cairo_atomic_intptr_t;
  88. #elif SIZEOF_VOID_P==SIZEOF_LONG
  89. typedef long cairo_atomic_intptr_t;
  90. #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
  91. typedef long long cairo_atomic_intptr_t;
  92. #else
  93. #error No matching integer pointer type
  94. #endif
  95.  
  96. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  97.     __sync_bool_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
  98.  
  99. # define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
  100.     _cairo_atomic_intptr_to_voidptr (__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv))
  101.  
  102. #endif
  103.  
  104. #if HAVE_LIB_ATOMIC_OPS
  105. #include <atomic_ops.h>
  106.  
  107. #define HAS_ATOMIC_OPS 1
  108.  
  109. typedef  AO_t cairo_atomic_int_t;
  110.  
  111. # define _cairo_atomic_int_get(x) (AO_load_full (x))
  112.  
  113. # define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
  114. # define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
  115. # define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
  116.  
  117. #if SIZEOF_VOID_P==SIZEOF_INT
  118. typedef unsigned int cairo_atomic_intptr_t;
  119. #elif SIZEOF_VOID_P==SIZEOF_LONG
  120. typedef unsigned long cairo_atomic_intptr_t;
  121. #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
  122. typedef unsigned long long cairo_atomic_intptr_t;
  123. #else
  124. #error No matching integer pointer type
  125. #endif
  126.  
  127. # define _cairo_atomic_ptr_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
  128. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  129.     _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
  130.  
  131. #endif
  132.  
  133. #if HAVE_OS_ATOMIC_OPS
  134. #include <libkern/OSAtomic.h>
  135.  
  136. #define HAS_ATOMIC_OPS 1
  137.  
  138. typedef int32_t cairo_atomic_int_t;
  139.  
  140. # define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
  141.  
  142. # define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
  143. # define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
  144. # define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
  145.  
  146. #if SIZEOF_VOID_P==4
  147. typedef int32_t cairo_atomic_intptr_t;
  148. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  149.     OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
  150.  
  151. #elif SIZEOF_VOID_P==8
  152. typedef int64_t cairo_atomic_intptr_t;
  153. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  154.     OSAtomicCompareAndSwap64Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
  155.  
  156. #else
  157. #error No matching integer pointer type
  158. #endif
  159.  
  160. # define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
  161.  
  162. #endif
  163.  
  164. #ifndef HAS_ATOMIC_OPS
  165.  
  166. #if SIZEOF_VOID_P==SIZEOF_INT
  167. typedef unsigned int cairo_atomic_intptr_t;
  168. #elif SIZEOF_VOID_P==SIZEOF_LONG
  169. typedef unsigned long cairo_atomic_intptr_t;
  170. #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
  171. typedef unsigned long long cairo_atomic_intptr_t;
  172. #else
  173. #error No matching integer pointer type
  174. #endif
  175.  
  176. typedef cairo_atomic_intptr_t cairo_atomic_int_t;
  177.  
  178. cairo_private void
  179. _cairo_atomic_int_inc (cairo_atomic_int_t *x);
  180.  
  181. cairo_private cairo_bool_t
  182. _cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
  183.  
  184. cairo_private cairo_atomic_int_t
  185. _cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv);
  186.  
  187. cairo_private void *
  188. _cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv);
  189.  
  190. #define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl (x, oldv, newv)
  191. #define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (x, oldv, newv)
  192.  
  193. #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
  194. cairo_private cairo_atomic_int_t
  195. _cairo_atomic_int_get (cairo_atomic_int_t *x);
  196. # define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x)
  197. #else
  198. # define _cairo_atomic_int_get(x) (*x)
  199. # define _cairo_atomic_ptr_get(x) (*x)
  200. #endif
  201.  
  202. #else
  203.  
  204. /* Workaround GCC complaining about casts */
  205. static cairo_always_inline void *
  206. _cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
  207. {
  208.   return (void *) x;
  209. }
  210.  
  211. static cairo_always_inline cairo_atomic_int_t
  212. _cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv)
  213. {
  214.     cairo_atomic_int_t curr;
  215.  
  216.     do {
  217.         curr = _cairo_atomic_int_get (x);
  218.     } while (curr == oldv && !_cairo_atomic_int_cmpxchg (x, oldv, newv));
  219.  
  220.     return curr;
  221. }
  222.  
  223. static cairo_always_inline void *
  224. _cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
  225. {
  226.     void *curr;
  227.  
  228.     do {
  229.         curr = _cairo_atomic_ptr_get (x);
  230.     } while (curr == oldv && !_cairo_atomic_ptr_cmpxchg (x, oldv, newv));
  231.  
  232.     return curr;
  233. }
  234. #endif
  235.  
  236. #ifndef _cairo_atomic_int_cmpxchg_return_old
  237. #define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_fallback (x, oldv, newv)
  238. #endif
  239.  
  240. #ifndef _cairo_atomic_ptr_cmpxchg_return_old
  241. #define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback (x, oldv, newv)
  242. #endif
  243.  
  244. #ifndef _cairo_atomic_int_cmpxchg
  245. #define _cairo_atomic_int_cmpxchg(x, oldv, newv) (_cairo_atomic_int_cmpxchg_return_old (x, oldv, newv) == oldv)
  246. #endif
  247.  
  248. #ifndef _cairo_atomic_ptr_cmpxchg
  249. #define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (_cairo_atomic_ptr_cmpxchg_return_old (x, oldv, newv) == oldv)
  250. #endif
  251.  
  252. #define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
  253. #define _cairo_atomic_uint_cmpxchg(x, oldv, newv) \
  254.     _cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)x, oldv, newv)
  255.  
  256. #define _cairo_status_set_error(status, err) do { \
  257.     /* hide compiler warnings about cairo_status_t != int (gcc treats its as \
  258.      * an unsigned integer instead, and about ignoring the return value. */  \
  259.     int ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \
  260.     (void) ret__; \
  261. } while (0)
  262.  
  263. CAIRO_END_DECLS
  264.  
  265. #endif
  266.