1 #include "lfds601_abstraction_internal.h"
\r
7 /****************************************************************************/
\r
8 #if (defined _WIN64 && defined _MSC_VER)
\r
10 /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
\r
12 _WIN64 indicates 64 bit Windows
\r
13 _MSC_VER indicates Microsoft C compiler
\r
16 LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value )
\r
21 assert( value != NULL );
\r
23 rv = _InterlockedIncrement64( (__int64 *) value );
\r
25 return( (lfds601_atom_t) rv );
\r
34 /****************************************************************************/
\r
35 #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
\r
37 /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
\r
39 (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows
\r
40 _MSC_VER indicates Microsoft C compiler
\r
43 LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value )
\r
48 assert( value != NULL );
\r
50 rv = _InterlockedIncrement( (long int *) value );
\r
52 return( (lfds601_atom_t) rv );
\r
61 /****************************************************************************/
\r
62 #if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
\r
64 /* TRD : any OS on any CPU with GCC 4.1.0 or better
\r
66 GCC 4.1.0 introduced the __sync_*() atomic intrinsics
\r
68 __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
\r
71 LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value )
\r
76 assert( value != NULL );
\r
78 // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
\r
80 rv = __sync_add_and_fetch( value, 1 );
\r
91 /****************************************************************************/
\r
92 #if (defined __arm__ && __GNUC__ >= 4)
\r
94 /* TRD : any OS on any CPU with GCC 4.1.0 or better
\r
96 GCC 4.1.0 introduced the __sync_*() atomic intrinsics
\r
98 __arm__ indicates ARM
\r
99 __GNUC__ indicates GCC
\r
102 LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value )
\r
108 assert( value != NULL );
\r
110 __asm__ __volatile__
\r
112 " mov %[stored_flag], #1;" // move 1 into stored_flag
\r
113 " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible)
\r
115 " ldrex %[new_value], [%[value]]; " // load *value into new_value
\r
116 " add %[new_value], #1;" // add 1 to new_value
\r
117 " strex %[stored_flag], %[new_value], [%[value]];" // try to store new_value into *value (on success, strex puts 0 into stored_flag)
\r
118 " teq %[stored_flag], #0;" // check if stored_flag is 0
\r
119 " bne atomic_add;" // if not 0, retry (someone else touched *value after we loaded but before we stored)
\r
120 " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible)
\r
123 : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag)
\r
126 : [value] "r" (value), [zero] "r" (0)
\r
129 : "cc", "memory" // memory is clobbered because we issue a memory barrier
\r
132 return( new_value );
\r