Modifying the return value of cfg_set* functions, in order to make
[sip-router] / atomic_ops.h
1 /* 
2  * $Id$
3  * 
4  * Copyright (C) 2006 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  *  atomic operations and memory barriers
20  *  WARNING: atomic ops do not include memory barriers
21  *  
22  *  memory barriers:
23  *  ----------------
24  *
25  *  void membar();        - memory barrier (load & store)
26  *  void membar_read()    - load (read) memory barrier
27  *  void membar_write()   - store (write) memory barrier
28  *  void membar_depends() - read depends memory barrier, needed before using
29  *                          the contents of a pointer (for now is needed only
30  *                          on Alpha so on all other CPUs it will be a no-op)
31  *                          For more info see: 
32  *                          http://lse.sourceforge.net/locking/wmbdd.html
33  *                          http://www.linuxjournal.com/article/8212
34  *
35  *  void membar_enter_lock() - memory barrier function that should be 
36  *                             called after a lock operation (where lock is
37  *                             an asm inline function that uses atomic store
38  *                             operation on the lock var.). It is at most
39  *                             a StoreStore|StoreLoad barrier, but could also
40  *                             be empty if an atomic op implies a memory 
41  *                             barrier on the specific arhitecture.
42  *                             Example usage: 
43  *                               raw_lock(l); membar_enter_lock(); ...
44  *  void membar_leave_lock() - memory barrier function that should be called 
45  *                             before an unlock operation (where unlock is an
46  *                             asm inline function that uses at least an atomic
47  *                             store to on the lock var.). It is at most a 
48  *                             LoadStore|StoreStore barrier (but could also be
49  *                             empty, see above).
50  *                             Example: raw_lock(l); membar_enter_lock(); ..
51  *                                      ... critical section ...
52  *                                      membar_leave_lock(); raw_unlock(l);
53  *  void membar_atomic_op() - memory barrier that should be called if a memory
54  *                            barrier is needed immediately after or 
55  *                            immediately before an atomic operation
56  *                            (for example: atomic_inc(&i); membar_atomic_op()
57  *                               instead of atomic_inc(&i); membar()).
58  *                            atomic_op means every atomic operation except get
59  *                            and set (for them use membar_atomic_setget()).
60  *                            Using membar_atomic_op() instead of membar() in
61  *                            these cases will generate faster code on some
62  *                            architectures (for now x86 and x86_64), where 
63  *                            atomic operations act also as memory barriers.
64  *                            Note that mb_atomic_<OP>(...) is equivalent to
65  *                            membar_atomic_op(); atomic_<OP>(...) and in this
66  *                            case the first form is preferred).
67  * void membar_atomic_setget() - same as above but for atomic_set and 
68  *                            atomic_get (and not for any other atomic op.,
69  *                            including atomic_get_and_set, for them use
70  *                            membar_atomic_op()).
71  *                            Note that mb_atomic_{get,set}(&i) is equivalent 
72  *                            and preferred to membar_atomic_setget(); 
73  *                            atomic_{get,set}(&i) (it will generate faster
74  *                            code on x86 and x86_64).
75  * void membar_read_atomic_op() - like membar_atomic_op(), but acts only as
76  *                             a read barrier.
77  * void membar_read_atomic_setget() - like membar_atomic_setget() but acts only
78  *                            as a read barrier.
79  * void membar_write_atomic_op() - like membar_atomic_op(), but acts only as
80  *                            a write barrier.
81  * void membar_write_atomic_setget() - like membar_atomic_setget() but acts 
82  *                            only as a write barrier.
83  *
84  *
85  *  Note: - properly using memory barriers is tricky, in general try not to 
86  *        depend on them. Locks include memory barriers, so you don't need
87  *        them for writes/load already protected by locks.
88  *        - membar_enter_lock() and membar_leave_lock() are needed only if
89  *        you implement your own locks using atomic ops (ser locks have the
90  *        membars included)
91  *
92  * atomic operations:
93  * ------------------
94  *  type: atomic_t
95  *
96  * not including memory barriers:
97  *
98  *  void atomic_set(atomic_t* v, int i)      - v->val=i
99  *  int atomic_get(atomic_t* v)              - return v->val
100  *  int atomic_get_and_set(atomic_t *v, i)   - return old v->val, v->val=i
101  *  void atomic_inc(atomic_t* v)
102  *  void atomic_dec(atomic_t* v)
103  *  int atomic_inc_and_test(atomic_t* v)     - returns 1 if the result is 0
104  *  int atomic_dec_and_test(atomic_t* v)     - returns 1 if the result is 0
105  *  void atomic_or (atomic_t* v, int mask)   - v->val|=mask 
106  *  void atomic_and(atomic_t* v, int mask)   - v->val&=mask
107  *  int atomic_add(atomic_t* v, int i)       - v->val+=i; return v->val
108  *  int atomic_cmpxchg(atomic_t* v, o, n)    - r=v->val; if (r==o) v->val=n;
109  *                                             return r (old value)
110  *
111  * 
112  * same ops, but with builtin memory barriers:
113  *
114  *  void mb_atomic_set(atomic_t* v, int i)      -  v->val=i
115  *  int mb_atomic_get(atomic_t* v)              -  return v->val
116  *  int mb_atomic_get_and_set(atomic_t *v, i)   -  return old v->val, v->val=i
117  *  void mb_atomic_inc(atomic_t* v)
118  *  void mb_atomic_dec(atomic_t* v)
119  *  int mb_atomic_inc_and_test(atomic_t* v)  - returns 1 if the result is 0
120  *  int mb_atomic_dec_and_test(atomic_t* v)  - returns 1 if the result is 0
121  *  void mb_atomic_or(atomic_t* v, int mask - v->val|=mask 
122  *  void mb_atomic_and(atomic_t* v, int mask)- v->val&=mask
123  *  int mb_atomic_add(atomic_t* v, int i)    - v->val+=i; return v->val
124  *  int mb_atomic_cmpxchg(atomic_t* v, o, n) - r=v->val; if (r==o) v->val=n;
125  *                                             return r (old value)
126  *
127  *  Same operations are available for int and long. The functions are named
128  *   after the following rules:
129  *     - add an int or long  suffix to the correspondent atomic function
130  *     -  volatile int* or volatile long* replace atomic_t* in the functions
131  *        declarations
132  *     -  long and int replace the parameter type (if the function has an extra
133  *        parameter) and the return value
134  *  E.g.:
135  *    long atomic_get_long(volatile long* v)
136  *    int atomic_get_int( volatile int* v)
137  *    long atomic_get_and_set(volatile long* v, long l)
138  *    int atomic_get_and_set(volatile int* v, int i)
139  *
140  * Config defines:   CC_GCC_LIKE_ASM  - the compiler support gcc style
141  *                     inline asm
142  *                   NOSMP - the code will be a little faster, but not SMP
143  *                            safe
144  *                   __CPU_i386, __CPU_x86_64, X86_OOSTORE - see 
145  *                       atomic/atomic_x86.h
146  *                   __CPU_mips, __CPU_mips2, __CPU_mips64, MIPS_HAS_LLSC - see
147  *                       atomic/atomic_mip2.h
148  *                   __CPU_ppc, __CPU_ppc64 - see atomic/atomic_ppc.h
149  *                   __CPU_sparc - see atomic/atomic_sparc.h
150  *                   __CPU_sparc64, SPARC64_MODE - see atomic/atomic_sparc64.h
151  *                   __CPU_arm, __CPU_arm6 - see atomic/atomic_arm.h
152  *                   __CPU_alpha - see atomic/atomic_alpha.h
153  */
154 /* 
155  * History:
156  * --------
157  *  2006-03-08  created by andrei
158  *  2007-05-13  moved some of the decl. and includes into atomic_common.h and 
159  *               atomic_native.h (andrei)
160  */
161 #ifndef __atomic_ops
162 #define __atomic_ops
163
164 #include "atomic/atomic_common.h"
165
166 #include "atomic/atomic_native.h"
167
168 /* if no native operations, emulate them using locks */
169 #if  ! defined HAVE_ASM_INLINE_ATOMIC_OPS || ! defined HAVE_ASM_INLINE_MEMBAR
170
171 #include "atomic/atomic_unknown.h"
172
173 #endif /* if HAVE_ASM_INLINE_ATOMIC_OPS */
174
175 #endif