1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #ifndef _h_atomic32_
28 #define _h_atomic32_
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /*
35 * Make sure gcc doesn't try to be clever and move things around
36 * on us. We need to use _exactly_ the address the user gave us,
37 * not some alias that contains the same information.
38 */
39 typedef struct atomic32_t atomic32_t;
40 struct atomic32_t
41 {
42 volatile int counter;
43 };
44
45 /* int atomic32_read ( const atomic32_t *v ); */
46 #define atomic32_read( v ) \
47 ( ( v ) -> counter )
48
49 /* void atomic32_set ( atomic32_t *v, int i ); */
50 #define atomic32_set( v, i ) \
51 ( ( void ) ( ( ( v ) -> counter ) = ( i ) ) )
52
53 /* add to v -> counter and return the prior value */
atomic32_read_and_add(atomic32_t * v,int i)54 static __inline__ int atomic32_read_and_add ( atomic32_t *v, int i )
55 {
56 return __sync_fetch_and_add( & v -> counter, i );
57 }
58
59 /* if no read is needed, define the least expensive atomic add */
60 #define atomic32_add( v, i ) \
61 atomic32_read_and_add ( v, i )
62
atomic32_dec(atomic32_t * v)63 static __inline__ void atomic32_dec ( atomic32_t *v )
64 {
65 atomic32_add( v, -1 );
66 }
67
atomic32_test_and_set(atomic32_t * v,int newval,int oldval)68 static __inline__ int atomic32_test_and_set ( atomic32_t *v, int newval, int oldval )
69 {
70 return __sync_val_compare_and_swap( & v -> counter, oldval, newval ); //NB: newval/oldval switched around
71 }
72
73 static __inline__
atomic32_read_and_add_gt(atomic32_t * v,int i,int t)74 int atomic32_read_and_add_gt ( atomic32_t *v, int i, int t )
75 {
76 int val, val_intern;
77 for ( val = atomic32_read ( v ); val > t; val = val_intern )
78 {
79 val_intern = atomic32_test_and_set ( v, val + i, val );
80 if ( val_intern == val )
81 break;
82 }
83 return val;
84 }
85
86 #ifdef __cplusplus
87 }
88 #endif
89
90 #endif /* _h_atomic32_ */
91
92