Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef _ink_atomic_h_
00038 #define _ink_atomic_h_
00039
00040 #include <stdio.h>
00041 #include <string.h>
00042 #include <stdint.h>
00043 #include <assert.h>
00044 #include "ink_defs.h"
00045
00046 #include "ink_apidefs.h"
00047 #include "ink_mutex.h"
00048
00049 typedef volatile int8_t vint8;
00050 typedef volatile int16_t vint16;
00051 typedef volatile int32_t vint32;
00052 typedef volatile int64_t vint64;
00053 typedef volatile uint64_t vuint64;
00054 typedef volatile long vlong;
00055 typedef volatile void *vvoidp;
00056
00057 typedef vint8 *pvint8;
00058 typedef vint16 *pvint16;
00059 typedef vint32 *pvint32;
00060 typedef vint64 *pvint64;
00061 typedef vuint64 *pvuint64;
00062 typedef vlong *pvlong;
00063 typedef vvoidp *pvvoidp;
00064
00065
00066 #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
00067
00068
00069
00070
00071
00072 template <typename T> static inline T
00073 ink_atomic_swap(volatile T * mem, T value) {
00074 return __sync_lock_test_and_set(mem, value);
00075 }
00076
00077
00078
00079
00080 template <typename T> static inline bool
00081 ink_atomic_cas(volatile T * mem, T prev, T next) {
00082 return __sync_bool_compare_and_swap(mem, prev, next);
00083 }
00084
00085
00086
00087 template <typename Type, typename Amount> static inline Type
00088 ink_atomic_increment(volatile Type * mem, Amount count) {
00089 return __sync_fetch_and_add(mem, (Type)count);
00090 }
00091
00092
00093
00094 template <typename Type, typename Amount> static inline Type
00095 ink_atomic_decrement(volatile Type * mem, Amount count) {
00096 return __sync_fetch_and_sub(mem, (Type)count);
00097 }
00098
00099
00100 #if (defined(__arm__) || defined(__mips__)) && (SIZEOF_VOIDP == 4)
00101 extern ink_mutex __global_death;
00102
00103 template<>
00104 inline int64_t
00105 ink_atomic_swap<int64_t>(pvint64 mem, int64_t value) {
00106 int64_t old;
00107 ink_mutex_acquire(&__global_death);
00108 old = *mem;
00109 *mem = value;
00110 ink_mutex_release(&__global_death);
00111 return old;
00112 }
00113
00114 template<>
00115 inline bool
00116 ink_atomic_cas<int64_t>(pvint64 mem, int64_t old, int64_t new_value) {
00117 int64_t curr;
00118 ink_mutex_acquire(&__global_death);
00119 curr = *mem;
00120 if(old == curr) *mem = new_value;
00121 ink_mutex_release(&__global_death);
00122 if(old == curr) return 1;
00123 return 0;
00124 }
00125
00126 template<typename Amount> static inline int64_t
00127 ink_atomic_increment(pvint64 mem, Amount value) {
00128 int64_t curr;
00129 ink_mutex_acquire(&__global_death);
00130 curr = *mem;
00131 *mem = curr + value;
00132 ink_mutex_release(&__global_death);
00133 return curr;
00134 }
00135
00136 template<typename Amount> static inline int64_t
00137 ink_atomic_decrement(pvint64 mem, Amount value) {
00138 int64_t curr;
00139 ink_mutex_acquire(&__global_death);
00140 curr = *mem;
00141 *mem = curr - value;
00142 ink_mutex_release(&__global_death);
00143 return curr;
00144 }
00145
00146 template<typename Amount> static inline uint64_t
00147 ink_atomic_increment(pvuint64 mem, Amount value) {
00148 uint64_t curr;
00149 ink_mutex_acquire(&__global_death);
00150 curr = *mem;
00151 *mem = curr + value;
00152 ink_mutex_release(&__global_death);
00153 return curr;
00154 }
00155
00156 template<typename Amount> static inline uint64_t
00157 ink_atomic_decrement(pvuint64 mem, Amount value) {
00158 uint64_t curr;
00159 ink_mutex_acquire(&__global_death);
00160 curr = *mem;
00161 *mem = curr - value;
00162 ink_mutex_release(&__global_death);
00163 return curr;
00164 }
00165
00166 #endif
00167
00168
00169 #define INK_WRITE_MEMORY_BARRIER
00170 #define INK_MEMORY_BARRIER
00171
00172
00173 #else
00174 #error Need a compiler / libc that supports atomic operations, e.g. gcc v4.1.2 or later
00175 #endif
00176
00177 #endif