00001 /* 00002 * $Id$ 00003 * 00004 * Copyright (C) 2006 iptelorg GmbH 00005 * 00006 * Permission to use, copy, modify, and distribute this software for any 00007 * purpose with or without fee is hereby granted, provided that the above 00008 * copyright notice and this permission notice appear in all copies. 00009 * 00010 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 00011 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00012 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 00013 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00014 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00015 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00016 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00017 */ 00018 00027 /* 00028 * \page atomicops Atomic operations and memory barriers 00029 * 00030 * WARNING: atomic ops do not include memory barriers 00031 * 00032 * memory barriers: 00033 * ---------------- 00034 * 00035 * void membar(); - memory barrier (load & store) 00036 * void membar_read() - load (read) memory barrier 00037 * void membar_write() - store (write) memory barrier 00038 * void membar_depends() - read depends memory barrier, needed before using 00039 * the contents of a pointer (for now is needed only 00040 * on Alpha so on all other CPUs it will be a no-op) 00041 * For more info see: 00042 * http://lse.sourceforge.net/locking/wmbdd.html 00043 * http://www.linuxjournal.com/article/8212 00044 * 00045 * void membar_enter_lock() - memory barrier function that should be 00046 * called after a lock operation (where lock is 00047 * an asm inline function that uses atomic store 00048 * operation on the lock var.). It is at most 00049 * a StoreStore|StoreLoad barrier, but could also 00050 * be empty if an atomic op implies a memory 00051 * barrier on the specific arhitecture. 00052 * Example usage: 00053 * raw_lock(l); membar_enter_lock(); ... 00054 * void membar_leave_lock() - memory barrier function that should be called 00055 * before an unlock operation (where unlock is an 00056 * asm inline function that uses at least an atomic 00057 * store to on the lock var.). It is at most a 00058 * LoadStore|StoreStore barrier (but could also be 00059 * empty, see above). 00060 * Example: raw_lock(l); membar_enter_lock(); .. 00061 * ... critical section ... 00062 * membar_leave_lock(); raw_unlock(l); 00063 * void membar_atomic_op() - memory barrier that should be called if a memory 00064 * barrier is needed immediately after or 00065 * immediately before an atomic operation 00066 * (for example: atomic_inc(&i); membar_atomic_op() 00067 * instead of atomic_inc(&i); membar()). 00068 * atomic_op means every atomic operation except get 00069 * and set (for them use membar_atomic_setget()). 00070 * Using membar_atomic_op() instead of membar() in 00071 * these cases will generate faster code on some 00072 * architectures (for now x86 and x86_64), where 00073 * atomic operations act also as memory barriers. 00074 * Note that mb_atomic_<OP>(...) is equivalent to 00075 * membar_atomic_op(); atomic_<OP>(...) and in this 00076 * case the first form is preferred). 00077 * void membar_atomic_setget() - same as above but for atomic_set and 00078 * atomic_get (and not for any other atomic op., 00079 * including atomic_get_and_set, for them use 00080 * membar_atomic_op()). 00081 * Note that mb_atomic_{get,set}(&i) is equivalent 00082 * and preferred to membar_atomic_setget(); 00083 * atomic_{get,set}(&i) (it will generate faster 00084 * code on x86 and x86_64). 00085 * void membar_read_atomic_op() - like membar_atomic_op(), but acts only as 00086 * a read barrier. 00087 * void membar_read_atomic_setget() - like membar_atomic_setget() but acts only 00088 * as a read barrier. 00089 * void membar_write_atomic_op() - like membar_atomic_op(), but acts only as 00090 * a write barrier. 00091 * void membar_write_atomic_setget() - like membar_atomic_setget() but acts 00092 * only as a write barrier. 00093 * 00094 * 00095 * Note: - properly using memory barriers is tricky, in general try not to 00096 * depend on them. Locks include memory barriers, so you don't need 00097 * them for writes/load already protected by locks. 00098 * - membar_enter_lock() and membar_leave_lock() are needed only if 00099 * you implement your own locks using atomic ops (ser locks have the 00100 * membars included) 00101 * 00102 * atomic operations: 00103 * ------------------ 00104 * type: atomic_t 00105 * 00106 * not including memory barriers: 00107 * 00108 * void atomic_set(atomic_t* v, int i) - v->val=i 00109 * int atomic_get(atomic_t* v) - return v->val 00110 * int atomic_get_and_set(atomic_t *v, i) - return old v->val, v->val=i 00111 * void atomic_inc(atomic_t* v) 00112 * void atomic_dec(atomic_t* v) 00113 * int atomic_inc_and_test(atomic_t* v) - returns 1 if the result is 0 00114 * int atomic_dec_and_test(atomic_t* v) - returns 1 if the result is 0 00115 * void atomic_or (atomic_t* v, int mask) - v->val|=mask 00116 * void atomic_and(atomic_t* v, int mask) - v->val&=mask 00117 * int atomic_add(atomic_t* v, int i) - v->val+=i; return v->val 00118 * int atomic_cmpxchg(atomic_t* v, o, n) - r=v->val; if (r==o) v->val=n; 00119 * return r (old value) 00120 * 00121 * 00122 * same ops, but with builtin memory barriers: 00123 * 00124 * void mb_atomic_set(atomic_t* v, int i) - v->val=i 00125 * int mb_atomic_get(atomic_t* v) - return v->val 00126 * int mb_atomic_get_and_set(atomic_t *v, i) - return old v->val, v->val=i 00127 * void mb_atomic_inc(atomic_t* v) 00128 * void mb_atomic_dec(atomic_t* v) 00129 * int mb_atomic_inc_and_test(atomic_t* v) - returns 1 if the result is 0 00130 * int mb_atomic_dec_and_test(atomic_t* v) - returns 1 if the result is 0 00131 * void mb_atomic_or(atomic_t* v, int mask - v->val|=mask 00132 * void mb_atomic_and(atomic_t* v, int mask)- v->val&=mask 00133 * int mb_atomic_add(atomic_t* v, int i) - v->val+=i; return v->val 00134 * int mb_atomic_cmpxchg(atomic_t* v, o, n) - r=v->val; if (r==o) v->val=n; 00135 * return r (old value) 00136 * 00137 * Same operations are available for int and long. The functions are named 00138 * after the following rules: 00139 * - add an int or long suffix to the correspondent atomic function 00140 * - volatile int* or volatile long* replace atomic_t* in the functions 00141 * declarations 00142 * - long and int replace the parameter type (if the function has an extra 00143 * parameter) and the return value 00144 * E.g.: 00145 * long atomic_get_long(volatile long* v) 00146 * int atomic_get_int( volatile int* v) 00147 * long atomic_get_and_set(volatile long* v, long l) 00148 * int atomic_get_and_set(volatile int* v, int i) 00149 * 00150 * Config defines: CC_GCC_LIKE_ASM - the compiler support gcc style 00151 * inline asm 00152 * NOSMP - the code will be a little faster, but not SMP 00153 * safe 00154 * __CPU_i386, __CPU_x86_64, X86_OOSTORE - see 00155 * atomic/atomic_x86.h 00156 * __CPU_mips, __CPU_mips2, __CPU_mips64, MIPS_HAS_LLSC - see 00157 * atomic/atomic_mip2.h 00158 * __CPU_ppc, __CPU_ppc64 - see atomic/atomic_ppc.h 00159 * __CPU_sparc - see atomic/atomic_sparc.h 00160 * __CPU_sparc64, SPARC64_MODE - see atomic/atomic_sparc64.h 00161 * __CPU_arm, __CPU_arm6 - see atomic/atomic_arm.h 00162 * __CPU_alpha - see atomic/atomic_alpha.h 00163 */ 00164 /* 00165 * History: 00166 * -------- 00167 * 2006-03-08 created by andrei 00168 * 2007-05-13 moved some of the decl. and includes into atomic_common.h and 00169 * atomic_native.h (andrei) 00170 */ 00171 #ifndef __atomic_ops 00172 #define __atomic_ops 00173 00174 #include "atomic/atomic_common.h" 00175 00176 #include "atomic/atomic_native.h" 00177 00179 #if ! defined HAVE_ASM_INLINE_ATOMIC_OPS || ! defined HAVE_ASM_INLINE_MEMBAR 00180 00181 #include "atomic/atomic_unknown.h" 00182 00183 #endif /* if HAVE_ASM_INLINE_ATOMIC_OPS */ 00184 00185 #endif
1.7.1