Back to index

php5  5.3.10
fpm_atomic.h
Go to the documentation of this file.
00001 
00002        /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
00003        /* (c) 2007,2008 Andrei Nigmatulin */
00004 
00005 #ifndef FPM_ATOMIC_H
00006 #define FPM_ATOMIC_H 1
00007 
00008 #if HAVE_INTTYPES_H
00009 # include <inttypes.h>
00010 #else
00011 # include <stdint.h>
00012 #endif
00013 #include <sched.h>
00014 
00015 #ifdef HAVE_BUILTIN_ATOMIC
00016 
00024 typedef volatile unsigned long atomic_t;
00025 #define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c)
00026 
00027 #elif ( __i386__ || __i386 )
00028 
00029 typedef int32_t                     atomic_int_t;
00030 typedef uint32_t                    atomic_uint_t;
00031 typedef volatile atomic_uint_t      atomic_t;
00032 
00033 
00034 static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add) /* {{{ */
00035 {
00036        __asm__ volatile ( "lock;" "xaddl %0, %1;" :
00037               "+r" (add) : "m" (*value) : "memory");
00038 
00039        return add;
00040 }
00041 /* }}} */
00042 
00043 static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) /* {{{ */
00044 {
00045        unsigned char res;
00046 
00047        __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
00048               "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
00049 
00050        return res;
00051 }
00052 /* }}} */
00053 
00054 #elif ( __amd64__ || __amd64 || __x86_64__ )
00055 
00056 typedef int64_t                     atomic_int_t;
00057 typedef uint64_t                    atomic_uint_t;
00058 typedef volatile atomic_uint_t      atomic_t;
00059 
00060 static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add) /* {{{ */
00061 {
00062        __asm__ volatile ( "lock;" "xaddq %0, %1;" :
00063               "+r" (add) : "m" (*value) : "memory");
00064 
00065        return add;
00066 }
00067 /* }}} */
00068 
00069 static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) /* {{{ */
00070 {
00071        unsigned char res;
00072 
00073        __asm__ volatile ( "lock;" "cmpxchgq %3, %1;" "sete %0;" :
00074               "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
00075 
00076        return res;
00077 }
00078 /* }}} */
00079 
00080 #if (__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
00081 
00082 #elif ( __arm__ || __arm ) /* W-Mark Kubacki */
00083 
00084 #if (__arch64__ || __arch64)
00085 typedef int64_t                     atomic_int_t;
00086 typedef uint64_t                    atomic_uint_t;
00087 #else
00088 typedef int32_t                     atomic_int_t;
00089 typedef uint32_t                    atomic_uint_t;
00090 #endif
00091 
00092 #define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c)
00093 
00094 #endif /* defined (__GNUC__) &&... */
00095 
00096 #elif ( __sparc__ || __sparc ) /* Marcin Ochab */
00097 
00098 #if (__sparcv9 || __sparcv9__)
00099 
00100 #if (__arch64__ || __arch64)
00101 typedef uint64_t                    atomic_uint_t;
00102 typedef volatile atomic_uint_t      atomic_t;
00103 
00104 static inline int atomic_cas_64(atomic_t *lock, atomic_uint_t old, atomic_uint_t new) /* {{{ */
00105 {
00106        __asm__ __volatile__("casx [%2], %3, %0 " : "=&r"(new)  : "0"(new), "r"(lock), "r"(old): "memory");
00107 
00108        return new;
00109 }
00110 /* }}} */
00111 
00112 static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) /* {{{ */
00113 {
00114        return (atomic_cas_64(lock, old, set)==old);
00115 }
00116 /* }}} */
00117 #else
00118 typedef uint32_t                    atomic_uint_t;
00119 typedef volatile atomic_uint_t      atomic_t;
00120 
00121 static inline int atomic_cas_32(atomic_t *lock, atomic_uint_t old, atomic_uint_t new) /* {{{ */
00122 {
00123        __asm__ __volatile__("cas [%2], %3, %0 " : "=&r"(new)  : "0"(new), "r"(lock), "r"(old): "memory");
00124 
00125        return new;
00126 }
00127 /* }}} */
00128 
00129 static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) /* {{{ */
00130 {
00131        return (atomic_cas_32(lock, old, set)==old);
00132 }
00133 /* }}} */
00134 #endif
00135 
00136 #else /* #if (__sparcv9 || __sparcv9__) */
00137 #error Sparc v8 and predecessors are not and will not be supported (see bug report 53310)
00138 #endif /* #if (__sparcv9 || __sparcv9__) */
00139 
00140 #else
00141 
00142 #error Unsupported processor. Please open a bug report (bugs.php.net).
00143 
00144 #endif
00145 
00146 static inline int fpm_spinlock(atomic_t *lock, int try_once) /* {{{ */
00147 {
00148        if (try_once) {
00149               return atomic_cmp_set(lock, 0, 1) ? 1 : 0;
00150        }
00151 
00152        for (;;) {
00153 
00154               if (atomic_cmp_set(lock, 0, 1)) {
00155                      break;
00156               }
00157 
00158               sched_yield();
00159        }
00160 
00161        return 1;
00162 }
00163 /* }}} */
00164 
00165 #define fpm_unlock(lock) lock = 0
00166 
00167 #endif
00168