Skip to content

Commit

Permalink
rwsem generic spinlock: use IRQ save/restore spinlocks
Browse files Browse the repository at this point in the history
rwsems can be used with IRQs disabled, particularily in early boot
before IRQs are enabled.  Currently the spin_unlock_irq() usage in the
slow-patch will unconditionally enable interrupts and cause problems
since interrupts are not yet initialized or enabled.

This patch uses save/restore versions of IRQ spinlocks in the slowpath
to ensure interrupts are not unintentionally disabled.

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
metaliveblog authored and torvalds committed Apr 7, 2010
1 parent 04287f9 commit 3eac4ab
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions lib/rwsem-spinlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,14 @@ void __sched __down_read(struct rw_semaphore *sem)
{
struct rwsem_waiter waiter;
struct task_struct *tsk;
unsigned long flags;

spin_lock_irq(&sem->wait_lock);
spin_lock_irqsave(&sem->wait_lock, flags);

if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
/* granted */
sem->activity++;
spin_unlock_irq(&sem->wait_lock);
spin_unlock_irqrestore(&sem->wait_lock, flags);
goto out;
}

Expand All @@ -164,7 +165,7 @@ void __sched __down_read(struct rw_semaphore *sem)
list_add_tail(&waiter.list, &sem->wait_list);

/* we don't need to touch the semaphore struct anymore */
spin_unlock_irq(&sem->wait_lock);
spin_unlock_irqrestore(&sem->wait_lock, flags);

/* wait to be given the lock */
for (;;) {
Expand Down Expand Up @@ -209,13 +210,14 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass)
{
struct rwsem_waiter waiter;
struct task_struct *tsk;
unsigned long flags;

spin_lock_irq(&sem->wait_lock);
spin_lock_irqsave(&sem->wait_lock, flags);

if (sem->activity == 0 && list_empty(&sem->wait_list)) {
/* granted */
sem->activity = -1;
spin_unlock_irq(&sem->wait_lock);
spin_unlock_irqrestore(&sem->wait_lock, flags);
goto out;
}

Expand All @@ -230,7 +232,7 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass)
list_add_tail(&waiter.list, &sem->wait_list);

/* we don't need to touch the semaphore struct anymore */
spin_unlock_irq(&sem->wait_lock);
spin_unlock_irqrestore(&sem->wait_lock, flags);

/* wait to be given the lock */
for (;;) {
Expand Down

0 comments on commit 3eac4ab

Please sign in to comment.