/* * 1,2 and 4 byte cmpxchg and xchg implementations for OpenRISC. * * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> * Copyright (C) 2017 Stafford Horne <shorne@gmail.com> * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. * * Note: * The portable implementations of 1 and 2 byte xchg and cmpxchg using a 4 * byte cmpxchg is sourced heavily from the sh and mips implementations.
*/
/* Do 32 bit cmpxchg */
load32 = cmpxchg_u32(p, old32, new32); if (load32 == old32) return old;
}
}
/* xchg */
staticinline u32 xchg_small(volatilevoid *ptr, u32 x, int size)
{ int off = (unsignedlong)ptr % sizeof(u32); volatile u32 *p = ptr - off; #ifdef __BIG_ENDIAN int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE; #else int bitoff = off * BITS_PER_BYTE; #endif
u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff;
u32 oldv, newv;
u32 ret;
do {
oldv = READ_ONCE(*p);
ret = (oldv & bitmask) >> bitoff;
newv = (oldv & ~bitmask) | (x << bitoff);
} while (cmpxchg_u32(p, oldv, newv) != oldv);
return ret;
}
/* * This function doesn't exist, so you'll get a linker error * if something tries to do an invalid cmpxchg().
*/ externunsignedlong __cmpxchg_called_with_bad_pointer(void)
__compiletime_error("Bad argument size for cmpxchg");
staticinlineunsignedlong __cmpxchg(volatilevoid *ptr, unsignedlong old, unsignedlongnew, int size)
{ switch (size) { case 1: case 2: return cmpxchg_small(ptr, old, new, size); case 4: return cmpxchg_u32(ptr, old, new); default: return __cmpxchg_called_with_bad_pointer();
}
}
/* * This function doesn't exist, so you'll get a linker error if * something tries to do an invalidly-sized xchg().
*/ externunsignedlong __xchg_called_with_bad_pointer(void)
__compiletime_error("Bad argument size for xchg");
staticinlineunsignedlong
__arch_xchg(volatilevoid *ptr, unsignedlong with, int size)
{ switch (size) { case 1: case 2: return xchg_small(ptr, with, size); case 4: return xchg_u32(ptr, with); default: return __xchg_called_with_bad_pointer();
}
}
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.