Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)/* * This file contains the implementation of spinlocks. It makes heavy use of * GCC's atomic built-ins for synchronization. The spinlocks have some simple * mechanisms for preventing deadlocks. Each spinlock knows which CPU/task is * holding it, and can allow that CPU/task to acquire it multiple times and * safely release it. */ #include <stdint.h> #include "task/task.h" #include "proc/proc.h" #include "spinlock.h" #include "screen.h" #include "io.h" /* Check if already holding */ static uint8_t holding(Spinlock *lock) { uint8_t r; r = lock->locked; r &= (current ? lock->task == current->tid : lock->cpu == CPUID); return r; } /* Create a new lock */ void init_lock(Spinlock *lock) { lock->locked = 0; lock->task = 0; lock->cpu = 0; lock->ref = 0; } /* Acquire a lock */ void acquire(Spinlock *lock) { /* * Reference count the lock so it can be safely acquired by the same * holder multiple times. This stops a lock from deadlocking itself. */ if (holding(lock)) { lock->ref++; return; } while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) asm volatile("pause"); __sync_synchronize(); if (current) lock->task = current->tid; lock->cpu = CPUID; } /* Release a lock */ void release(Spinlock *lock) { if (!holding(lock)) panic("Cannot release unheld lock"); if (lock->ref) { lock->ref--; return; } lock->task = 0; lock->cpu = 0; __sync_lock_release(&lock->locked); __sync_synchronize(); }