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