]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_increment.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.0.0 / liblfds600 / src / lfds600_abstraction / lfds600_abstraction_increment.c
1 #include "lfds600_abstraction_internal.h"
2
3
4
5
6
7 /****************************************************************************/
8 #if (defined _WIN64 && defined _MSC_VER)
9
10   /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
11
12            _WIN64    indicates 64 bit Windows
13            _MSC_VER  indicates Microsoft C compiler
14   */
15
16   LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
17   {
18     __int64
19       rv;
20
21     assert( value != NULL );
22
23     rv = _InterlockedIncrement64( (__int64 *) value );
24
25     return( (lfds600_atom_t) rv );
26   }
27
28 #endif
29
30
31
32
33
34 /****************************************************************************/
35 #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
36
37   /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
38
39            (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
40            _MSC_VER                             indicates Microsoft C compiler
41   */
42
43   LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
44   {
45     long int
46       rv;
47
48     assert( value != NULL );
49
50     rv = _InterlockedIncrement( (long int *) value );
51
52     return( (lfds600_atom_t) rv );
53   }
54
55 #endif
56
57
58
59
60
61 /****************************************************************************/
62 #if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
63
64   /* TRD : any OS on any CPU with GCC 4.1.0 or better
65
66            GCC 4.1.0 introduced the __sync_*() atomic intrinsics
67
68            __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
69   */
70
71   LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
72   {
73     lfds600_atom_t
74       rv;
75
76     assert( value != NULL );
77
78     // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
79
80     rv = __sync_add_and_fetch( value, 1 );
81
82     return( rv );
83   }
84
85 #endif
86
87
88
89
90
91 /****************************************************************************/
92 #if (defined __arm__ && __GNUC__ >= 4)
93
94   /* TRD : any OS on any CPU with GCC 4.1.0 or better
95
96            GCC 4.1.0 introduced the __sync_*() atomic intrinsics
97
98            __arm__   indicates ARM
99            __GNUC__  indicates GCC
100   */
101
102   LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
103   {
104     lfds600_atom_t
105       stored_flag = 0,
106       new_value = 0;
107
108     assert( value != NULL );
109
110     __asm__ __volatile__
111     (
112       "  mov    %[stored_flag], #1;"                        // move 1 into stored_flag
113       "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
114       "atomic_add:;"
115       "  ldrex  %[new_value], [%[value]];  "                // load *value into new_value
116       "  add    %[new_value], #1;"                          // add 1 to new_value
117       "  strex  %[stored_flag], %[new_value], [%[value]];"  // try to store new_value into *value (on success, strex puts 0 into stored_flag)
118       "  teq    %[stored_flag], #0;"                        // check if stored_flag is 0
119       "  bne    atomic_add;"                                // if not 0, retry (someone else touched *value after we loaded but before we stored)
120       "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
121
122       // output
123       : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag)
124
125       // input
126       : [value] "r" (value), [zero] "r" (0)
127
128       // clobbered
129       : "cc", "memory"                                      // memory is clobbered because we issue a memory barrier
130     );
131
132     return( new_value );
133   }
134
135 #endif
136