| 58 | | |
| 59 | | /**************** |
| 60 | | * First, we'll define some memory barrier primitives based on the system. |
| 61 | | * right now only OS X, FreeBSD, and Linux are supported. In addition to providing |
| 62 | | * memory barriers, these functions should ensure that data cached in registers |
| 63 | | * is written out to cache where it can be snooped by other CPUs. (ie, the volatile |
| 64 | | * keyword should not be required) |
| 65 | | * |
| 66 | | * the primitives that must be defined are: |
| 67 | | * |
| 68 | | * PaUtil_FullMemoryBarrier() |
| 69 | | * PaUtil_ReadMemoryBarrier() |
| 70 | | * PaUtil_WriteMemoryBarrier() |
| 71 | | * |
| 72 | | ****************/ |
| 73 | | |
| 74 | | #if defined(__APPLE__) |
| 75 | | # include <libkern/OSAtomic.h> |
| 76 | | /* Here are the memory barrier functions. Mac OS X only provides |
| 77 | | full memory barriers, so the three types of barriers are the same, |
| 78 | | however, these barriers are superior to compiler-based ones. */ |
| 79 | | # define PaUtil_FullMemoryBarrier() OSMemoryBarrier() |
| 80 | | # define PaUtil_ReadMemoryBarrier() OSMemoryBarrier() |
| 81 | | # define PaUtil_WriteMemoryBarrier() OSMemoryBarrier() |
| 82 | | #elif defined(__GNUC__) |
| 83 | | /* GCC >= 4.1 has built-in intrinsics. We'll use those */ |
| 84 | | # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) |
| 85 | | # define PaUtil_FullMemoryBarrier() __sync_synchronize() |
| 86 | | # define PaUtil_ReadMemoryBarrier() __sync_synchronize() |
| 87 | | # define PaUtil_WriteMemoryBarrier() __sync_synchronize() |
| 88 | | /* as a fallback, GCC understands volatile asm and "memory" to mean it |
| 89 | | * should not reorder memory read/writes */ |
| 90 | | # elif defined( __PPC__ ) |
| 91 | | # define PaUtil_FullMemoryBarrier() asm volatile("sync":::"memory") |
| 92 | | # define PaUtil_ReadMemoryBarrier() asm volatile("sync":::"memory") |
| 93 | | # define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory") |
| 94 | | # elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || defined( __i686__ ) || defined( __x86_64__ ) |
| 95 | | # define PaUtil_FullMemoryBarrier() asm volatile("mfence":::"memory") |
| 96 | | # define PaUtil_ReadMemoryBarrier() asm volatile("lfence":::"memory") |
| 97 | | # define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory") |
| 98 | | # else |
| 99 | | # ifdef ALLOW_SMP_DANGERS |
| 100 | | # warning Memory barriers not defined on this system or system unknown |
| 101 | | # warning For SMP safety, you should fix this. |
| 102 | | # define PaUtil_FullMemoryBarrier() |
| 103 | | # define PaUtil_ReadMemoryBarrier() |
| 104 | | # define PaUtil_WriteMemoryBarrier() |
| 105 | | # else |
| 106 | | # error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed. |
| 107 | | # endif |
| 108 | | # endif |
| 109 | | #else |
| 110 | | # ifdef ALLOW_SMP_DANGERS |
| 111 | | # warning Memory barriers not defined on this system or system unknown |
| 112 | | # warning For SMP safety, you should fix this. |
| 113 | | # define PaUtil_FullMemoryBarrier() |
| 114 | | # define PaUtil_ReadMemoryBarrier() |
| 115 | | # define PaUtil_WriteMemoryBarrier() |
| 116 | | # else |
| 117 | | # error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed. |
| 118 | | # endif |
| 119 | | #endif |
| | 58 | #include "pa_memorybarrier.h" |