fix atomic for K210. enable print mutex again

toolchain_update
WangRunji 6 years ago
parent 70b6db4282
commit 9ab4fd40ea

@ -1,91 +1,131 @@
// http://llvm.org/docs/Atomics.html#libcalls-atomic
int __atomic_load_1(int *src) {
int res = 0;
__asm__ __volatile__("amoadd.w.rl %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
typedef unsigned u32;
// K210 doesn't support atomic operation on 0x40000000 (io port)
// We have to detect it and move it to 0x80000000
inline u32* fix_ptr32(u32 *src) {
return (u32)src < 0x80000000?
(u32*)((u32)src + 0x40000000):
src;
}
u32 __atomic_load_1(u32 *src) {
src = fix_ptr32(src);
u32 res = 0;
__asm__ __volatile__("amoadd.w %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
return res;
}
int __atomic_load_2(int *src) {
int res = 0;
__asm__ __volatile__("amoadd.w.rl %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
u32 __atomic_load_2(u32 *src) {
src = fix_ptr32(src);
u32 res = 0;
__asm__ __volatile__("amoadd.w %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
return res;
}
int __atomic_load_4(int *src) {
int res = 0;
__asm__ __volatile__("amoadd.w.rl %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
u32 __atomic_load_4(u32 *src) {
src = fix_ptr32(src);
u32 res = 0;
__asm__ __volatile__("amoadd.w %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
return res;
}
int __atomic_store_4(int *dst, int val) {
__asm__ __volatile__("amoswap.w.aq zero, %0, (%1)" :: "r"(val), "r"(dst) : "memory");
void __atomic_store_4(u32 *dst, u32 val) {
dst = fix_ptr32(dst);
__asm__ __volatile__("amoswap.w zero, %0, (%1)" :: "r"(val), "r"(dst) : "memory");
}
char __atomic_compare_exchange_4(int* dst, int* expected, int desired) {
int val;
char __atomic_compare_exchange_4(u32* dst, u32* expected, u32 desired) {
dst = fix_ptr32(dst);
u32 val, expect, result;
// val = *dst
__asm__ __volatile__("lw %0, (%1)" : "=r"(expect) : "r" (expected) : "memory");
__asm__ __volatile__("lr.w %0, (%1)" : "=r"(val) : "r"(dst) : "memory");
if (val == *expected) {
int result;
// Try: *dst = desired. If success, result = 0, otherwise result != 0.
__asm__ __volatile__("sc.w %0, %1, (%2)" : "=r"(result) : "r"(desired), "r"(dst) : "memory");
return result == 0;
}
// if (val != *expected) goto fail;
if (val != expect) goto __atomic_compare_exchange_4_fail;
// Try: *dst = desired. If success, result = 0, otherwise result != 0.
__asm__ __volatile__("sc.w %0, %1, (%2)" : "=r"(result) : "r"(desired), "r"(dst) : "memory");
return result == 0;
__atomic_compare_exchange_4_fail:
// *expected should always equal to the previous value of *dst
*expected = val;
return 0;
}
int __atomic_fetch_add_4(int* ptr, int val) {
int res;
__asm__ __volatile__("amoadd.w.rl %0, %1, (%2)" : "=r"(res) : "r"(val), "r"(ptr) : "memory");
u32 __atomic_fetch_add_4(u32* ptr, u32 val) {
ptr = fix_ptr32(ptr);
u32 res;
__asm__ __volatile__("amoadd.w %0, %1, (%2)" : "=r"(res) : "r"(val), "r"(ptr) : "memory");
return res;
}
int __atomic_fetch_sub_4(int* ptr, int val) {
int res;
__asm__ __volatile__("amoadd.w.rl %0, %1, (%2)" : "=r"(res) : "r"(-val), "r"(ptr) : "memory");
u32 __atomic_fetch_sub_4(u32* ptr, u32 val) {
ptr = fix_ptr32(ptr);
u32 res;
__asm__ __volatile__("amoadd.w %0, %1, (%2)" : "=r"(res) : "r"(-val), "r"(ptr) : "memory");
return res;
}
#ifdef TARGET_IS_64BITS
#if __riscv_xlen == 64
typedef unsigned long long u64;
// K210 doesn't support atomic operation on 0x40000000 (io port)
// We have to detect it and move it to 0x80000000
inline u64* fix_ptr64(u64 *src) {
return (u64)src < 0x80000000?
(u64*)((u64)src + 0x40000000):
src;
}
u64 __atomic_load_8(u64 *src) {
src = fix_ptr64(src);
u64 res = 0;
__asm__ __volatile__("amoadd.d.rl %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
__asm__ __volatile__("amoadd.d %0, zero, (%1)" : "=r"(res) : "r"(src) : "memory");
return res;
}
u64 __atomic_store_8(u64 *dst, u64 val) {
__asm__ __volatile__("amoswap.d.aq zero, %0, (%1)" :: "r"(val), "r"(dst) : "memory");
void __atomic_store_8(u64 *dst, u64 val) {
dst = fix_ptr64(dst);
__asm__ __volatile__("amoswap.d zero, %0, (%1)" :: "r"(val), "r"(dst) : "memory");
}
char __atomic_compare_exchange_8(u64* dst, u64* expected, u64 desired) {
u64 val;
dst = fix_ptr64(dst);
u64 val, expect, result;
// val = *dst
__asm__ __volatile__("ld %0, (%1)" : "=r"(expect) : "r" (expected) : "memory");
__asm__ __volatile__("lr.d %0, (%1)" : "=r"(val) : "r"(dst) : "memory");
if (val == *expected) {
u64 result;
// Try: *dst = desired. If success, result = 0, otherwise result != 0.
__asm__ __volatile__("sc.d %0, %1, (%2)" : "=r"(result) : "r"(desired), "r"(dst) : "memory");
return result == 0;
}
// if (val != *expected) goto fail;
if (val != expect) goto __atomic_compare_exchange_8_fail;
// Try: *dst = desired. If success, result = 0, otherwise result != 0.
__asm__ __volatile__("sc.d %0, %1, (%2)" : "=r"(result) : "r"(desired), "r"(dst) : "memory");
return result == 0;
__atomic_compare_exchange_8_fail:
// *expected should always equal to the previous value of *dst
*expected = val;
return 0;
}
u64 __atomic_fetch_add_8(u64* ptr, u64 val) {
ptr = fix_ptr64(ptr);
u64 res;
__asm__ __volatile__("amoadd.d.rl %0, %1, (%2)" : "=r"(res) : "r"(val), "r"(ptr) : "memory");
__asm__ __volatile__("amoadd.d %0, %1, (%2)" : "=r"(res) : "r"(val), "r"(ptr) : "memory");
return res;
}
u64 __atomic_fetch_sub_8(u64* ptr, u64 val) {
ptr = fix_ptr64(ptr);
u64 res;
__asm__ __volatile__("amoadd.d.rl %0, %1, (%2)" : "=r"(res) : "r"(-val), "r"(ptr) : "memory");
__asm__ __volatile__("amoadd.d %0, %1, (%2)" : "=r"(res) : "r"(-val), "r"(ptr) : "memory");
return res;
}
#endif

@ -44,13 +44,13 @@ macro_rules! with_color {
fn print_in_color(args: fmt::Arguments, color: Color) {
use crate::arch::io;
// let mutex = log_mutex.lock();
let mutex = log_mutex.lock();
io::putfmt(with_color!(args, color));
}
pub fn print(args: fmt::Arguments) {
use crate::arch::io;
// let mutex = log_mutex.lock();
let mutex = log_mutex.lock();
io::putfmt(args);
}

Loading…
Cancel
Save