Go to the source code of this file.
Defines | |
#define | LOCK "lock;" |
#define | compiler_barrier() __asm__ __volatile__ ("":::"memory") |
#define | LFENCE __asm__ __volatile__ ("lfence":::"memory") |
#define | SFENCE __asm__ __volatile__ ("sfence":::"memory") |
#define | CC_FENCE __asm__ __volatile__ ("mfence":::"memory") |
Functions | |
int | getProcessNum () |
bool | cas (volatile void *address, void *oldV_a, unsigned long newV, int size) |
Do CAS operation on address specified by parameter address . | |
bool | casd (volatile void *ptr, void *old_addr, const void *new_v) |
This function is used to do CAS to two consecutive machine words. | |
unsigned long | xchg (volatile void *ptr, unsigned long v, int size) |
atomically exchange content of two variables | |
Variables | |
const int | CACHE_PER_CORE = 512000 |
const int | CACHE_LINE_SIZE = 64 |
#define CC_FENCE __asm__ __volatile__ ("mfence":::"memory") |
#define compiler_barrier | ( | ) | __asm__ __volatile__ ("":::"memory") |
#define LFENCE __asm__ __volatile__ ("lfence":::"memory") |
According to David Dice's understanding, http://blogs.sun.com/dave/entry/java_memory_model_concerns_on, recent x86 manuals have relaxed the hardware memory model. mfence doesn't get sequential consistency any more. So here we discriminate CC fence from SC fence...
#define LOCK "lock;" |
#define SFENCE __asm__ __volatile__ ("sfence":::"memory") |
bool cas | ( | volatile void * | address, | |
void * | oldV_a, | |||
unsigned long | newV, | |||
int | size | |||
) | [inline] |
Do CAS operation on address specified by parameter address
.
CAS is the abbrev. for Compare and Swap or Compare and Set, which is a very important instruction for implementing lock-free algorithm. This instruction can do following steps atomically:
address | The memory address to be updated atomicially | |
oldV_a | A pointer to the old value. Only if the value referenced by address equals to the old value, CompareAndSet operation can succeed. | |
newV | The new value which will be put to address when CAS succeeds | |
size | The number of bytes that cas should handle. It can be 1,2, and 4 on 32-bit platform and 1,2,4, and 8 on 64-bit platform. |
bool casd | ( | volatile void * | ptr, | |
void * | old_addr, | |||
const void * | new_v | |||
) | [inline] |
This function is used to do CAS to two consecutive machine words.
Since normal cas() can at most apply to one machine word which has as many bits as address line. This function aims to provide CAS operation on double width data. Eg, for 32bit platform, this function can operate 64bit data; for 64bit platform, this function can operate 128bit data.
ptr | The memory address to be updated atomicially | |
old_addr | A pointer to the old value. Only if the value referenced by address equals to the old value, CompareAndSet operation can succeed. | |
new_v | The new value which will be put to address when CAS succeeds |
int getProcessNum | ( | ) | [inline] |
unsigned long xchg | ( | volatile void * | ptr, | |
unsigned long | v, | |||
int | size | |||
) | [inline] |
atomically exchange content of two variables
For "swap" operation. xchg always implies a full memory barrier on X86, even without LOCK prefix. It essentially stores the value v into ptr, and return the value in ptr before the store operation. I am not quite sure return "unsigned long" will meet the demand, also for qualifiers of "v"
const int CACHE_LINE_SIZE = 64 |
const int CACHE_PER_CORE = 512000 |