text: /*
   * Copyright (c) 2014 Travis Geiselbrecht
   *
   * Permission is hereby granted, free of charge, to any person obtaining
   * a copy of this software and associated documentation files
   * (the "Software"), to deal in the Software without restriction,
   * including without limitation the rights to use, copy, modify, merge,
   * publish, distribute, sublicense, and/or sell copies of the Software,
   * and to permit persons to whom the Software is furnished to do so,
   * subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   */
  #pragma once
  
  #include <compiler.h>
  #include <arch/spinlock.h>
  
  __BEGIN_CDECLS
  
  /* interrupts should already be disabled */
  static inline void spin_lock(spin_lock_t *lock)
  {
      arch_spin_lock(lock);
  }
  
  /* Returns 0 on success, non-0 on failure */
  static inline int spin_trylock(spin_lock_t *lock)
  {
      return arch_spin_trylock(lock);
  }
  
  /* interrupts should already be disabled */
  static inline void spin_unlock(spin_lock_t *lock)
  {
      arch_spin_unlock(lock);
  }
  
  static inline void spin_lock_init(spin_lock_t *lock)
  {
      arch_spin_lock_init(lock);
  }
  
  static inline bool spin_lock_held(spin_lock_t *lock)
  {
      return arch_spin_lock_held(lock);
  }
  
  /* spin lock irq save flags: */
  
  /* Possible future flags:
   * SPIN_LOCK_FLAG_PMR_MASK         = 0x000000ff
   * SPIN_LOCK_FLAG_PREEMPTION       = 0x00000100
   * SPIN_LOCK_FLAG_SET_PMR          = 0x00000200
   */
  
  /* Generic flags */
  #define SPIN_LOCK_FLAG_INTERRUPTS ARCH_DEFAULT_SPIN_LOCK_FLAG_INTERRUPTS
  
  /* same as spin lock, but save disable and save interrupt state first */
  static inline void spin_lock_save(
      spin_lock_t *lock,
      spin_lock_saved_state_t *statep,
      spin_lock_save_flags_t flags)
  {
      arch_interrupt_save(statep, flags);
      spin_lock(lock);
  }
  
  /* restore interrupt state before unlocking */
  static inline void spin_unlock_restore(
      spin_lock_t *lock,
      spin_lock_saved_state_t old_state,
      spin_lock_save_flags_t flags)
  {
      spin_unlock(lock);
      arch_interrupt_restore(old_state, flags);
  }
  
  /* hand(ier) routines */
  #define spin_lock_irqsave(lock, statep) spin_lock_save(lock, &(statep), SPIN_LOCK_FLAG_INTERRUPTS)
  #define spin_unlock_irqrestore(lock, statep) spin_unlock_restore(lock, statep, SPIN_LOCK_FLAG_INTERRUPTS)
  
  __END_CDECLS
  