Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | 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(x) ((void) __sync_fetch_and_add(x, -1))
  83. # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
  84. # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
  85. # define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
  86.  
  87. #if SIZEOF_VOID_P==SIZEOF_INT
  88. typedef int cairo_atomic_intptr_t;
  89. #elif SIZEOF_VOID_P==SIZEOF_LONG
  90. typedef long cairo_atomic_intptr_t;
  91. #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
  92. typedef long long cairo_atomic_intptr_t;
  93. #else
  94. #error No matching integer pointer type
  95. #endif
  96.  
  97. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  98.     __sync_bool_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
  99.  
  100. # define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
  101.     _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))
  102.  
  103. #endif
  104.  
  105. #if HAVE_LIB_ATOMIC_OPS
  106. #include <atomic_ops.h>
  107.  
  108. #define HAS_ATOMIC_OPS 1
  109.  
  110. typedef  AO_t cairo_atomic_int_t;
  111.  
  112. # define _cairo_atomic_int_get(x) (AO_load_full (x))
  113.  
  114. # define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
  115. # define _cairo_atomic_int_dec(x) ((void) AO_fetch_and_sub1_full(x))
  116. # define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
  117. # define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
  118.  
  119. #if SIZEOF_VOID_P==SIZEOF_INT
  120. typedef unsigned int cairo_atomic_intptr_t;
  121. #elif SIZEOF_VOID_P==SIZEOF_LONG
  122. typedef unsigned long cairo_atomic_intptr_t;
  123. #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
  124. typedef unsigned long long cairo_atomic_intptr_t;
  125. #else
  126. #error No matching integer pointer type
  127. #endif
  128.  
  129. # define _cairo_atomic_ptr_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
  130. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  131.     _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
  132.  
  133. #endif
  134.  
  135. #if HAVE_OS_ATOMIC_OPS
  136. #include <libkern/OSAtomic.h>
  137.  
  138. #define HAS_ATOMIC_OPS 1
  139.  
  140. typedef int32_t cairo_atomic_int_t;
  141.  
  142. # define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
  143.  
  144. # define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
  145. # define _cairo_atomic_int_dec(x) ((void) OSAtomicDecrement32Barrier (x))
  146. # define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
  147. # define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
  148.  
  149. #if SIZEOF_VOID_P==4
  150. typedef int32_t cairo_atomic_intptr_t;
  151. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  152.     OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
  153.  
  154. #elif SIZEOF_VOID_P==8
  155. typedef int64_t cairo_atomic_intptr_t;
  156. # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
  157.     OSAtomicCompareAndSwap64Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
  158.  
  159. #else
  160. #error No matching integer pointer type
  161. #endif
  162.  
  163. # define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
  164.  
  165. #endif
  166.  
  167. #ifndef HAS_ATOMIC_OPS
  168.  
  169. #if SIZEOF_VOID_P==SIZEOF_INT
  170. typedef unsigned int cairo_atomic_intptr_t;
  171. #elif SIZEOF_VOID_P==SIZEOF_LONG
  172. typedef unsigned long cairo_atomic_intptr_t;
  173. #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
  174. typedef unsigned long long cairo_atomic_intptr_t;
  175. #else
  176. #error No matching integer pointer type
  177. #endif
  178.  
  179. typedef cairo_atomic_intptr_t cairo_atomic_int_t;
  180.  
  181. cairo_private void
  182. _cairo_atomic_int_inc (cairo_atomic_int_t *x);
  183.  
  184. #define _cairo_atomic_int_dec(x) _cairo_atomic_int_dec_and_test(x)
  185.  
  186. cairo_private cairo_bool_t
  187. _cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
  188.  
  189. cairo_private cairo_atomic_int_t
  190. _cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv);
  191.  
  192. cairo_private void *
  193. _cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv);
  194.  
  195. #define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl (x, oldv, newv)
  196. #define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (x, oldv, newv)
  197.  
  198. #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
  199. cairo_private cairo_atomic_int_t
  200. _cairo_atomic_int_get (cairo_atomic_int_t *x);
  201. # define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x)
  202. #else
  203. # define _cairo_atomic_int_get(x) (*x)
  204. # define _cairo_atomic_ptr_get(x) (*x)
  205. #endif
  206.  
  207. #else
  208.  
  209. /* Workaround GCC complaining about casts */
  210. static cairo_always_inline void *
  211. _cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
  212. {
  213.   return (void *) x;
  214. }
  215.  
  216. static cairo_always_inline cairo_atomic_int_t
  217. _cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv)
  218. {
  219.     cairo_atomic_int_t curr;
  220.  
  221.     do {
  222.         curr = _cairo_atomic_int_get (x);
  223.     } while (curr == oldv && !_cairo_atomic_int_cmpxchg (x, oldv, newv));
  224.  
  225.     return curr;
  226. }
  227.  
  228. static cairo_always_inline void *
  229. _cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
  230. {
  231.     void *curr;
  232.  
  233.     do {
  234.         curr = _cairo_atomic_ptr_get (x);
  235.     } while (curr == oldv && !_cairo_atomic_ptr_cmpxchg (x, oldv, newv));
  236.  
  237.     return curr;
  238. }
  239. #endif
  240.  
  241. #ifndef _cairo_atomic_int_cmpxchg_return_old
  242. #define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_fallback (x, oldv, newv)
  243. #endif
  244.  
  245. #ifndef _cairo_atomic_ptr_cmpxchg_return_old
  246. #define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback (x, oldv, newv)
  247. #endif
  248.  
  249. #ifndef _cairo_atomic_int_cmpxchg
  250. #define _cairo_atomic_int_cmpxchg(x, oldv, newv) (_cairo_atomic_int_cmpxchg_return_old (x, oldv, newv) == oldv)
  251. #endif
  252.  
  253. #ifndef _cairo_atomic_ptr_cmpxchg
  254. #define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (_cairo_atomic_ptr_cmpxchg_return_old (x, oldv, newv) == oldv)
  255. #endif
  256.  
  257. #define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
  258. #define _cairo_atomic_uint_cmpxchg(x, oldv, newv) \
  259.     _cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)x, oldv, newv)
  260.  
  261. #define _cairo_status_set_error(status, err) do { \
  262.     int ret__; \
  263.     assert (err < CAIRO_STATUS_LAST_STATUS); \
  264.     /* hide compiler warnings about cairo_status_t != int (gcc treats its as \
  265.      * an unsigned integer instead, and about ignoring the return value. */  \
  266.     ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \
  267.     (void) ret__; \
  268. } while (0)
  269.  
  270. CAIRO_END_DECLS
  271.  
  272. #endif
  273.