* This class is used to restrict instruction reordering within a CPU in * order to maintain synchronization properties between threads. Is a thin * wrapper around x86 "fence" instructions. Note: getting fencing correct * is extremely tricky! Whenever possible, use existing solutions that already * handle the fencing. */
| 25 | * handle the fencing. |
| 26 | */ |
| 27 | class Fence { |
| 28 | public: |
| 29 | |
| 30 | /** |
| 31 | * This method creates a boundary across which load instructions cannot |
| 32 | * migrate: if a memory read comes from code occurring before (after) |
| 33 | * invoking this method, the read is guaranteed to complete before (after) |
| 34 | * the method is invoked. |
| 35 | */ |
| 36 | static void inline lfence() |
| 37 | { |
| 38 | __asm__ __volatile__("lfence" ::: "memory"); |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * This method creates a boundary across which store instructions cannot |
| 43 | * migrate: if a memory store comes from code occurring before (after) |
| 44 | * invoking this method, the store is guaranteed to complete before (after) |
| 45 | * the method is invoked. |
| 46 | */ |
| 47 | static void inline sfence() |
| 48 | { |
| 49 | __asm__ __volatile__("sfence" ::: "memory"); |
| 50 | } |
| 51 | |
| 52 | /** |
| 53 | * This method provides appropriate fencing for the beginning of a critical |
| 54 | * section. Normally this method is invoked immediately after performing |
| 55 | * synchronization to enter a critical section, such as acquiring a lock. |
| 56 | * It guarantees the following: |
| 57 | * - Loads coming from code following this method will see any changes |
| 58 | * made to memory by other threads before the method is invoked. |
| 59 | * - Stores coming from code following this method will be reflected |
| 60 | * in memory after the method is invoked. Note: this property depends |
| 61 | * on the existence of branch instructions in the synchronization step |
| 62 | * that precedes this method (stores cannot be reflected in memory until |
| 63 | * after any preceding branches have been resolved). |
| 64 | */ |
| 65 | static void inline enter() |
| 66 | { |
| 67 | lfence(); |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * This method provides appropriate fencing for the end of a critical |
| 72 | * section. Normally this method is invoked immediately prior to releasing |
| 73 | * the lock for the critical section. It guarantees the following: |
| 74 | * - Loads coming from code preceding this method will complete before the |
| 75 | * method returns, so they will not see any changes made to memory by other |
| 76 | * threads after the method is invoked. |
| 77 | * - Stores coming from code preceding this method will be reflected |
| 78 | * in memory before the method returns, so when the next thread enters |
| 79 | * the critical section it is guaranteed to see any changes made in the |
| 80 | * current critical section. |
| 81 | */ |
| 82 | static void inline leave() |
| 83 | { |
| 84 | sfence(); |
nothing calls this directly
no outgoing calls
no test coverage detected