(root)/
fontconfig-2.14.2/
src/
fcatomic.h
       1  /*
       2   * Mutex operations.  Originally copied from HarfBuzz.
       3   *
       4   * Copyright © 2007  Chris Wilson
       5   * Copyright © 2009,2010  Red Hat, Inc.
       6   * Copyright © 2011,2012,2013  Google, Inc.
       7   *
       8   * Permission is hereby granted, without written agreement and without
       9   * license or royalty fees, to use, copy, modify, and distribute this
      10   * software and its documentation for any purpose, provided that the
      11   * above copyright notice and the following two paragraphs appear in
      12   * all copies of this software.
      13   *
      14   * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
      15   * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
      16   * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
      17   * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
      18   * DAMAGE.
      19   *
      20   * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
      21   * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      22   * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
      23   * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
      24   * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      25   *
      26   * Contributor(s):
      27   *	Chris Wilson <chris@chris-wilson.co.uk>
      28   * Red Hat Author(s): Behdad Esfahbod
      29   * Google Author(s): Behdad Esfahbod
      30   */
      31  
      32  #ifndef _FCATOMIC_H_
      33  #define _FCATOMIC_H_
      34  
      35  #ifdef HAVE_CONFIG_H
      36  #include <config.h>
      37  #endif
      38  
      39  
      40  /* atomic_int */
      41  
      42  /* We need external help for these */
      43  
      44  #if 0
      45  
      46  typedef <type> fc_atomic_int_t;
      47  #define FC_ATOMIC_INT_FORMAT		"<printf format for fc_atomic_int_t>"
      48  #define fc_atomic_int_add(AI, V)	o = (AI), (AI) += (V), o // atomic acquire/release
      49  
      50  #define fc_atomic_ptr_get(P)		*(P) // atomic acquire
      51  #define fc_atomic_ptr_cmpexch(P,O,N)	*(P) == (O) ? (*(P) = (N), FcTrue) : FcFalse // atomic release
      52  
      53  
      54  #elif !defined(FC_NO_MT) && defined(HAVE_STDATOMIC_PRIMITIVES)
      55  
      56  #include <stdatomic.h>
      57  
      58  typedef atomic_int fc_atomic_int_t;
      59  #define FC_ATOMIC_INT_FORMAT		"d"
      60  #define fc_atomic_int_add(AI, V)	atomic_fetch_add_explicit (&(AI), (V), memory_order_acq_rel)
      61  
      62  #define fc_atomic_ptr_get(P)		atomic_load_explicit ((_Atomic(void *)*) (P), memory_order_acquire)
      63  static inline FcBool _fc_atomic_ptr_cmpexch(_Atomic(void *)*P, void * O, _Atomic(void *) N) {
      64    return atomic_compare_exchange_strong_explicit(P, &O, N, memory_order_release, memory_order_relaxed);
      65  }
      66  #define fc_atomic_ptr_cmpexch(P,O,N)	_fc_atomic_ptr_cmpexch ((_Atomic(void *)*) (P), (O), (N))
      67  
      68  /* Casting -1 to _Atomic(int) produces a compiler error with Clang (but not GCC)
      69   * so we have to override FC_REF_CONSTANT_VALUE for stdatomic.h atomics.
      70   * See https://bugs.llvm.org/show_bug.cgi?id=40249. */
      71  #define FC_REF_CONSTANT_VALUE (-1)
      72  
      73  #elif !defined(FC_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
      74  
      75  #include "fcwindows.h"
      76  
      77  typedef LONG fc_atomic_int_t;
      78  #define FC_ATOMIC_INT_FORMAT		"ld"
      79  #define fc_atomic_int_add(AI, V)	InterlockedExchangeAdd (&(AI), (V))
      80  
      81  #define fc_atomic_ptr_get(P)		(InterlockedCompareExchangePointerAcquire ((void **) (P), NULL, NULL))
      82  #define fc_atomic_ptr_cmpexch(P,O,N)	(InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
      83  
      84  
      85  #elif !defined(FC_NO_MT) && defined(__APPLE__)
      86  
      87  #include <libkern/OSAtomic.h>
      88  #include <AvailabilityMacros.h>
      89  
      90  typedef int fc_atomic_int_t;
      91  #define FC_ATOMIC_INT_FORMAT		"d"
      92  #define fc_atomic_int_add(AI, V)	(OSAtomicAdd32Barrier ((V), &(AI)) - (V))
      93  
      94  #if SIZEOF_VOID_P == 8
      95  #define fc_atomic_ptr_get(P)		OSAtomicAdd64Barrier (0, (int64_t*)(P))
      96  #elif SIZEOF_VOID_P == 4
      97  #define fc_atomic_ptr_get(P)		OSAtomicAdd32Barrier (0, (int32_t*)(P))
      98  #else
      99  #error "SIZEOF_VOID_P not 4 or 8 (assumes CHAR_BIT is 8)"
     100  #endif
     101  
     102  #if (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 20100)
     103  #define fc_atomic_ptr_cmpexch(P,O,N)	OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
     104  #else
     105  #if __LP64__
     106  #define fc_atomic_ptr_cmpexch(P,O,N)	OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t *) (P))
     107  #else
     108  #define fc_atomic_ptr_cmpexch(P,O,N)	OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t *) (P))
     109  #endif
     110  #endif
     111  
     112  
     113  #elif !defined(FC_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
     114  
     115  typedef int fc_atomic_int_t;
     116  #define FC_ATOMIC_INT_FORMAT		"d"
     117  #define fc_atomic_int_add(AI, V)	__sync_fetch_and_add (&(AI), (V))
     118  
     119  #define fc_atomic_ptr_get(P)		(void *) (__sync_fetch_and_add ((P), 0))
     120  #define fc_atomic_ptr_cmpexch(P,O,N)	__sync_bool_compare_and_swap ((P), (O), (N))
     121  
     122  
     123  #elif !defined(FC_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
     124  
     125  #include <atomic.h>
     126  #include <mbarrier.h>
     127  
     128  typedef unsigned int fc_atomic_int_t;
     129  #define FC_ATOMIC_INT_FORMAT		"u"
     130  #define fc_atomic_int_add(AI, V)	( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
     131  
     132  #define fc_atomic_ptr_get(P)		( ({__machine_rw_barrier ();}), (void *) *(P))
     133  #define fc_atomic_ptr_cmpexch(P,O,N)	( ({__machine_rw_barrier ();}), atomic_cas_ptr ((P), (O), (N)) == (void *) (O) ? FcTrue : FcFalse)
     134  
     135  
     136  #elif !defined(FC_NO_MT)
     137  
     138  #define FC_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
     139  typedef volatile int fc_atomic_int_t;
     140  #define FC_ATOMIC_INT_FORMAT		"d"
     141  #define fc_atomic_int_add(AI, V)	(((AI) += (V)) - (V))
     142  
     143  #define fc_atomic_ptr_get(P)		((void *) *(P))
     144  #define fc_atomic_ptr_cmpexch(P,O,N)	(* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), FcTrue) : FcFalse)
     145  
     146  
     147  #else /* FC_NO_MT */
     148  
     149  typedef int fc_atomic_int_t;
     150  #define FC_ATOMIC_INT_FORMAT		"d"
     151  #define fc_atomic_int_add(AI, V)	(((AI) += (V)) - (V))
     152  
     153  #define fc_atomic_ptr_get(P)		((void *) *(P))
     154  #define fc_atomic_ptr_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), FcTrue) : FcFalse)
     155  
     156  #endif
     157  
     158  /* reference count */
     159  #ifndef FC_REF_CONSTANT_VALUE
     160  #define FC_REF_CONSTANT_VALUE ((fc_atomic_int_t) -1)
     161  #endif
     162  #define FC_REF_CONSTANT {FC_REF_CONSTANT_VALUE}
     163  typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
     164  static inline void   FcRefInit     (FcRef *r, int v) { r->count = v; }
     165  static inline int    FcRefInc      (FcRef *r) { return fc_atomic_int_add (r->count, +1); }
     166  static inline int    FcRefDec      (FcRef *r) { return fc_atomic_int_add (r->count, -1); }
     167  static inline int    FcRefAdd      (FcRef *r, int v) { return fc_atomic_int_add (r->count, v); }
     168  static inline void   FcRefSetConst (FcRef *r) { r->count = FC_REF_CONSTANT_VALUE; }
     169  static inline FcBool FcRefIsConst  (const FcRef *r) { return r->count == FC_REF_CONSTANT_VALUE; }
     170  
     171  #endif /* _FCATOMIC_H_ */