#include #include "init.h" typedef struct { int counter; } atomic_t; static inline int atomic_xchg(atomic_t *v, int n) { register int c; __asm__ __volatile__ ( "amoswap.w.aqrl %0, %2, %1" : "=r" (c), "+A" (v->counter) : "r" (n)); return c; } static inline void mb(void) { __asm__ __volatile__ ("fence"); } void get_lock(atomic_t *lock) { while (atomic_xchg(lock, 1) == 1) ; mb(); } void put_lock(atomic_t *lock) { mb(); atomic_xchg(lock, 0); } static atomic_t buf_lock = { .counter = 0 }; static char buf[32]; static int buf_initialized; static unsigned hart_count[NHARTS]; static unsigned interrupt_count[NHARTS]; static unsigned delta = 0x100; void *increment_count(unsigned hartid, unsigned mcause, void *mepc, void *sp) { interrupt_count[hartid]++; MTIMECMP[hartid] = MTIME + delta; return mepc; } int main() { uint32_t hartid = csr_read(mhartid); hart_count[hartid] = 0; interrupt_count[hartid] = 0; set_trap_handler(increment_count); // Despite being memory-mapped, there appears to be one mtimecmp // register per hart. The spec does not address this. MTIMECMP[hartid] = MTIME + delta; enable_timer_interrupts(); while (1) { get_lock(&buf_lock); if (!buf_initialized) { for (unsigned i = 0; i < sizeof(buf); i++) { buf[i] = 'A' + (i % 26); } buf_initialized = 1; } char first = buf[0]; int offset = (first & ~0x20) - 'A'; for (unsigned i = 0; i < sizeof(buf); i++) { while (buf[i] != (first - offset + ((offset + i) % 26))) ; if (hartid & 1) buf[i] = 'A' + ((i + hartid + hart_count[hartid]) % 26); else buf[i] = 'a' + ((i + hartid + hart_count[hartid]) % 26); } put_lock(&buf_lock); hart_count[hartid]++; } }