/* * Use 4 byte cas instruction to achieve 2 byte xchg. Main logic * here is to get the bit shift of the byte we are interested in. * The XOR is handy for reversing the bits for big-endian byte order.
*/ staticinlineunsignedlong
xchg16(__volatile__ unsignedshort *m, unsignedshort val)
{ unsignedlong maddr = (unsignedlong)m; int bit_shift = (((unsignedlong)m & 2) ^ 2) << 3; unsignedint mask = 0xffff << bit_shift; unsignedint *ptr = (unsignedint *) (maddr & ~2); unsignedint old32, new32, load32;
/* Read the old value */
load32 = *ptr;
do {
old32 = load32;
new32 = (load32 & (~mask)) | val << bit_shift;
load32 = __cmpxchg_u32(ptr, old32, new32);
} while (load32 != old32);
return (load32 & mask) >> bit_shift;
}
static __always_inline unsignedlong
__arch_xchg(unsignedlong x, __volatile__ void * ptr, int size)
{ switch (size) { case 2: return xchg16(ptr, x); case 4: return xchg32(ptr, x); case 8: return xchg64(ptr, x);
}
__xchg_called_with_bad_pointer(); return x;
}
/* * Atomic compare and exchange. Compare OLD with MEM, if identical, * store NEW in MEM. Return the initial value in MEM. Success is * indicated by comparing RETURN with OLD.
*/
/* * Use 4 byte cas instruction to achieve 1 byte cmpxchg. Main logic * here is to get the bit shift of the byte we are interested in. * The XOR is handy for reversing the bits for big-endian byte order
*/ staticinlineunsignedlong
__cmpxchg_u8(volatileunsignedchar *m, unsignedchar old, unsignedcharnew)
{ unsignedlong maddr = (unsignedlong)m; int bit_shift = (((unsignedlong)m & 3) ^ 3) << 3; unsignedint mask = 0xff << bit_shift; unsignedint *ptr = (unsignedint *) (maddr & ~3); unsignedint old32, new32, load; unsignedint load32 = *ptr;
/* This function doesn't exist, so you'll get a linker error
if something tries to do an invalid cmpxchg(). */ void __cmpxchg_called_with_bad_pointer(void);
staticinlineunsignedlong
__cmpxchg(volatilevoid *ptr, unsignedlong old, unsignedlongnew, int size)
{ switch (size) { case 1: return __cmpxchg_u8(ptr, old, new); case 4: return __cmpxchg_u32(ptr, old, new); case 8: return __cmpxchg_u64(ptr, old, new);
}
__cmpxchg_called_with_bad_pointer(); return old;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.