1 #include "lfds600_abstraction_internal.h"
7 /****************************************************************************/
8 #if (defined _WIN64 && defined _MSC_VER)
10 /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
12 _WIN64 indicates 64 bit Windows
13 _MSC_VER indicates Microsoft C compiler
16 LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
21 assert( value != NULL );
23 rv = _InterlockedIncrement64( (__int64 *) value );
25 return( (lfds600_atom_t) rv );
34 /****************************************************************************/
35 #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
37 /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
39 (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows
40 _MSC_VER indicates Microsoft C compiler
43 LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
48 assert( value != NULL );
50 rv = _InterlockedIncrement( (long int *) value );
52 return( (lfds600_atom_t) rv );
61 /****************************************************************************/
62 #if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
64 /* TRD : any OS on any CPU with GCC 4.1.0 or better
66 GCC 4.1.0 introduced the __sync_*() atomic intrinsics
68 __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
71 LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
76 assert( value != NULL );
78 // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
80 rv = __sync_add_and_fetch( value, 1 );
91 /****************************************************************************/
92 #if (defined __arm__ && __GNUC__ >= 4)
94 /* TRD : any OS on any CPU with GCC 4.1.0 or better
96 GCC 4.1.0 introduced the __sync_*() atomic intrinsics
99 __GNUC__ indicates GCC
102 LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value )
108 assert( value != NULL );
112 " mov %[stored_flag], #1;" // move 1 into stored_flag
113 " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible)
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)
123 : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag)
126 : [value] "r" (value), [zero] "r" (0)
129 : "cc", "memory" // memory is clobbered because we issue a memory barrier