123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- /* vim: tabstop=4 shiftwidth=4 noexpandtab
- * This file is part of ToaruOS and is released under the terms
- * of the NCSA / University of Illinois License - see LICENSE.md
- * Copyright (C) 2015 Dale Weiler
- *
- * Spin locks with waiters
- *
- */
- #include <kernel/system.h>
- static inline int arch_atomic_swap(volatile int * x, int v) {
- asm("xchg %0, %1" : "=r"(v), "=m"(*x) : "0"(v) : "memory");
- return v;
- }
- static inline void arch_atomic_store(volatile int * p, int x) {
- asm("movl %1, %0" : "=m"(*p) : "r"(x) : "memory");
- }
- static inline void arch_atomic_inc(volatile int * x) {
- asm("lock; incl %0" : "=m"(*x) : "m"(*x) : "memory");
- }
- static inline void arch_atomic_dec(volatile int * x) {
- asm("lock; decl %0" : "=m"(*x) : "m"(*x) : "memory");
- }
- void spin_wait(volatile int * addr, volatile int * waiters) {
- if (waiters) {
- arch_atomic_inc(waiters);
- }
- while (*addr) {
- switch_task(1);
- }
- if (waiters) {
- arch_atomic_dec(waiters);
- }
- }
- void spin_lock(spin_lock_t lock) {
- while (arch_atomic_swap(lock, 1)) {
- spin_wait(lock, lock+1);
- }
- }
- void spin_init(spin_lock_t lock) {
- lock[0] = 0;
- lock[1] = 0;
- }
- void spin_unlock(spin_lock_t lock) {
- if (lock[0]) {
- arch_atomic_store(lock, 0);
- if (lock[1])
- switch_task(1);
- }
- }
|