• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

atomic_ops.h

Go to the documentation of this file.
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

Generated on Tue May 22 2012 13:10:02 for SIP Router by  doxygen 1.7.1