diff options
Diffstat (limited to 'include/cpu')
-rw-r--r-- | include/cpu/atomic/swap.h | 40 | ||||
-rw-r--r-- | include/cpu/irq.h | 23 |
2 files changed, 63 insertions, 0 deletions
diff --git a/include/cpu/atomic/swap.h b/include/cpu/atomic/swap.h new file mode 100644 index 0000000..cbed62c --- /dev/null +++ b/include/cpu/atomic/swap.h @@ -0,0 +1,40 @@ +#ifndef CPU_ATOMIC_SWAP_A_H +#define CPU_ATOMIC_SWAP_A_H +#include "../../util/mutex.h" + +/// https://stackoverflow.com/questions/16329123/use-of-strexeq-instead-of-strex-for-spinlock-implementation-in-arm +/// https://elixir.bootlin.com/linux/v4.9/source/arch/arm/include/asm/spinlock.h +/// https://elixir.bootlin.com/linux/v4.9/source/arch/arm/include/asm/spinlock_types.h#L23 +/// https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/3_Processes.html +/// https://developer.arm.com/documentation/dht0008/a/arm-synchronization-primitives/practical-uses/implementing-a-semaphore?lang=en + +// TODO: Once scheduling works, have a failed lock put thread in waiting state +static inline void atm_lock(unsigned long pid, unsigned long* addr) +{ + unsigned long tmp, current_lock_value; + asm volatile( +"1: ldrex %0, [%3]\n" +" cmp %0, #0\n" +" wfene\n" +" strexeq %1, %2, [%3]\n" +" teq %1, #0\n" +" bne 1b\n" +" dmb" + : "=&r" (current_lock_value), "=&r" (tmp) + : "r" (pid), "r" (addr) + : "cc"); +} + +static inline void atm_release(unsigned long* addr) +{ + unsigned long cleared = NULL_PID; + asm volatile( +" dmb\n" +" str %0, [%1]\n" +" dsb\n" +" sev" + :: "r" (cleared), "r" (addr) + : "cc"); +} + +#endif diff --git a/include/cpu/irq.h b/include/cpu/irq.h new file mode 100644 index 0000000..3b8f085 --- /dev/null +++ b/include/cpu/irq.h @@ -0,0 +1,23 @@ +#ifndef CPU_IRQ_H +#define CPU_IRQ_H + +static inline void enableirq(void) +{ + asm volatile("cpsie i"); +} +static inline void disableirq(void) +{ + asm volatile("cpsid i"); +} +static inline void enablefiq(void) +{ + asm volatile("cpsie f"); +} +static inline void disablefiq(void) +{ + asm volatile("cpsid f"); +} + +void c_irq_handler(void); + +#endif |