Index: kernel/generic/src/synch/spinlock.c
===================================================================
--- kernel/generic/src/synch/spinlock.c	(revision 2b4a9f26cedf64d7586d2e0b91cc522a8d4fc07b)
+++ kernel/generic/src/synch/spinlock.c	(revision a9f1372b10ddc3484d0e257123b300c46a7ef03e)
@@ -169,4 +169,149 @@
 #endif
 
+/** Initialize interrupts-disabled spinlock
+ *
+ * @param lock IRQ spinlock to be initialized.
+ * @param name IRQ spinlock name.
+ *
+ */
+void irq_spinlock_initialize(irq_spinlock_t *lock, const char *name)
+{
+	spinlock_initialize(&(lock->lock), name);
+	lock->guard = false;
+	lock->ipl = 0;
+}
+
+/** Lock interrupts-disabled spinlock
+ *
+ * Lock a spinlock which requires disabled interrupts.
+ *
+ * @param lock    IRQ spinlock to be locked.
+ * @param irq_dis If true, interrupts are actually disabled
+ *                prior locking the spinlock. If false, interrupts
+ *                are expected to be already disabled.
+ *
+ */
+void irq_spinlock_lock(irq_spinlock_t *lock, bool irq_dis)
+{
+	if (irq_dis) {
+		ipl_t ipl = interrupts_disable();
+		spinlock_lock(&(lock->lock));
+		
+		lock->guard = true;
+		lock->ipl = ipl;
+	} else {
+		ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
+		
+		spinlock_lock(&(lock->lock));
+		ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
+	}
+}
+
+/** Unlock interrupts-disabled spinlock
+ *
+ * Unlock a spinlock which requires disabled interrupts.
+ *
+ * @param lock    IRQ spinlock to be unlocked.
+ * @param irq_res If true, interrupts are restored to previously
+ *                saved interrupt level.
+ *
+ */
+void irq_spinlock_unlock(irq_spinlock_t *lock, bool irq_res)
+{
+	ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
+	
+	if (irq_res) {
+		ASSERT_IRQ_SPINLOCK(lock->guard, lock);
+		
+		lock->guard = false;
+		ipl_t ipl = lock->ipl;
+		
+		spinlock_unlock(&(lock->lock));
+		interrupts_restore(ipl);
+	} else {
+		ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
+		spinlock_unlock(&(lock->lock));
+	}
+}
+
+/** Lock interrupts-disabled spinlock
+ *
+ * Lock an interrupts-disabled spinlock conditionally. If the
+ * spinlock is not available at the moment, signal failure.
+ * Interrupts are expected to be already disabled.
+ *
+ * @param lock IRQ spinlock to be locked conditionally.
+ *
+ * @return Zero on failure, non-zero otherwise.
+ *
+ */
+int irq_spinlock_trylock(irq_spinlock_t *lock)
+{
+	ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
+	int rc = spinlock_trylock(&(lock->lock));
+	
+	ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
+	return rc;
+}
+
+/** Pass lock from one interrupts-disabled spinlock to another
+ *
+ * Pass lock from one IRQ spinlock to another IRQ spinlock
+ * without enabling interrupts during the process.
+ *
+ * The first IRQ spinlock is supposed to be locked.
+ *
+ * @param unlock IRQ spinlock to be unlocked.
+ * @param lock   IRQ spinlock to be locked.
+ *
+ */
+void irq_spinlock_pass(irq_spinlock_t *unlock, irq_spinlock_t *lock)
+{
+	ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock);
+	
+	/* Pass guard from unlock to lock */
+	bool guard = unlock->guard;
+	ipl_t ipl = unlock->ipl;
+	unlock->guard = false;
+	
+	spinlock_unlock(&(unlock->lock));
+	spinlock_lock(&(lock->lock));
+	
+	ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
+	
+	if (guard) {
+		lock->guard = true;
+		lock->ipl = ipl;
+	}
+}
+
+/** Hand-over-hand locking of interrupts-disabled spinlocks
+ *
+ * Implement hand-over-hand locking between two interrupts-disabled
+ * spinlocks without enabling interrupts during the process.
+ *
+ * The first IRQ spinlock is supposed to be locked.
+ *
+ * @param unlock IRQ spinlock to be unlocked.
+ * @param lock   IRQ spinlock to be locked.
+ *
+ */
+void irq_spinlock_exchange(irq_spinlock_t *unlock, irq_spinlock_t *lock)
+{
+	ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock);
+	
+	spinlock_lock(&(lock->lock));
+	ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
+	
+	/* Pass guard from unlock to lock */
+	if (unlock->guard) {
+		lock->guard = true;
+		lock->ipl = unlock->ipl;
+		unlock->guard = false;
+	}
+	
+	spinlock_unlock(&(unlock->lock));
+}
+
 /** @}
  */
