win-pvdrivers

view liblfds.6/src/single_dir_for_windows_kernel/abstraction_cas.c @ 1025:aa2e51f67f7c

Fix hibernate under Win8. Change debugprints.
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 19 15:14:53 2013 +1100 (2013-02-19)
parents 6300617040e0
children
line source
1 #include "abstraction_internal.h"
7 /****************************************************************************/
8 #if (defined _WIN32 && defined _MSC_VER)
10 /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
12 _WIN32 indicates 64-bit or 32-bit Windows
13 _MSC_VER indicates Microsoft C compiler
14 */
16 INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
17 {
18 assert( destination != NULL );
19 // TRD : exchange can be any value in its range
20 // TRD : compare can be any value in its range
22 return( (atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) );
23 }
25 #endif
31 /****************************************************************************/
32 #if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
34 /* TRD : any OS on any CPU except ARM with GCC 4.1.0 or better
36 GCC 4.1.0 introduced the __sync_*() atomic intrinsics
38 __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
39 */
41 INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
42 {
43 assert( destination != NULL );
44 // TRD : exchange can be any value in its range
45 // TRD : compare can be any value in its range
47 // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic
49 return( (atom_t) __sync_val_compare_and_swap(destination, compare, exchange) );
50 }
52 #endif
58 /****************************************************************************/
59 #if (defined __arm__ && __GNUC__)
61 /* TRD : any OS on any ARM with GCC
63 Remember however we need to set into compare the original value of destination.
65 __arm__ indicates ARM
66 __GNUC__ indicates GCC
67 */
69 INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
70 {
71 atom_t
72 stored_flag,
73 original_destination;
75 assert( destination != NULL );
76 // TRD : exchange can be any value in its range
77 // TRD : compare can be any value in its range
79 /* TRD : this is a standard, plain CAS, vulnerable to ABA */
81 __asm__ __volatile__
82 (
83 " mov %[stored_flag], #1;" // put 1 into stored_flag
84 " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible)
85 "atomic_cas:;"
86 " ldrex %[original_destination], [%[destination]];" // load *destination into original_destination
87 " teq %[original_destination], %[compare];" // compare original_destination with compare
88 " bne exit;" // if not equal, exit
89 " strex %[stored_flag], %[exchange], [%[destination]];" // if equal, try to store exchange into *destination (on success, strex puts 0 into stored_flag)
90 " teq %[stored_flag], #0;" // check if stored_flag is 0
91 " bne atomic_cas;" // if not 0, retry (someone else touched *destination after we loaded but before we stored)
92 " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible)
93 "exit:;"
95 // output
96 : "+m" (*destination), [original_destination] "=&r" (original_destination), [stored_flag] "=&r" (stored_flag)
98 // input
99 : [destination] "r" (destination), [compare] "r" (compare), [exchange] "r" (exchange), [zero] "r" (0)
101 // clobbered
102 : "cc", "memory" // memory is clobbered because we issue a memory barrier
103 );
105 return( original_destination );
106 }
108 #endif