1/* 2 * RISC-V atomic operations 3 * assumes A extension 4 */ 5 6#define LINK R1 7#define SP R2 8#define ARG 8 9 10#define SYNC WORD $0xf /* FENCE */ 11#define LRW(rs2, rs1, rd) \ 12 WORD $((2<<27)|( 0<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057) 13#define SCW(rs2, rs1, rd) \ 14 WORD $((3<<27)|((rs2)<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057) 15 16TEXT ainc(SB), 1, $-4 /* long ainc(long *); */ 17 MOVW R(ARG), R12 /* address of counter */ 18 SYNC 19loop: 20 MOVW $1, R13 21 LRW(0, 12, ARG) // LR_W R0, R12, R(ARG) /* (R12) -> R(ARG) */ 22 ADD R(ARG), R13 23 MOVW R13, R(ARG) /* return new value */ 24 SCW(13, 12, 14) // SC_W R13, R12, R14 /* R13 -> (R12) maybe, R14=0 if ok */ 25 BNE R14, loop 26 RET 27 28TEXT adec(SB), 1, $-4 /* long adec(long*); */ 29 MOVW R(ARG), R12 /* address of counter */ 30 SYNC 31loop1: 32 MOVW $-1, R13 33 LRW(0, 12, ARG) // LR_W R0, R12, R(ARG) /* (R12) -> R(ARG) */ 34 ADD R(ARG), R13 35 MOVW R13, R(ARG) /* return new value */ 36 SCW(13, 12, 14) // SC_W R13, R12, R14 /* R13 -> (R12) maybe, R14=0 if ok */ 37 BNE R14, loop1 38 RET 39 40/* 41 * int cas(uint* p, int ov, int nv); 42 * 43 * compare-and-swap: atomically set *addr to nv only if it contains ov, 44 * and returns the old value. this version returns 0 on success, -1 on failure 45 * instead. 46 */ 47TEXT cas(SB), 1, $-4 48 MOVW ov+4(FP), R12 49 MOVW nv+8(FP), R13 50 SYNC 51spincas: 52 LRW(0, ARG, 14) // LR_W R0, R(ARG), R14 /* (R(ARG)) -> R14 */ 53 BNE R12, R14, fail 54 SCW(13, ARG, 14) // SC_W R13, R(ARG), R14 /* R13 -> (R(ARG)) maybe, R14=0 if ok */ 55 BNE R14, spincas /* R14 != 0 means store failed */ 56 MOVW $1, R(ARG) 57 RET 58fail: 59 MOVW R0, R(ARG) 60 RET 61