diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-04-07 22:04:12 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-04-07 22:04:12 +0000 |
commit | 4057679b76ae5e1f7e79802be8399396f29c0b09 (patch) | |
tree | ee0e7deeda4465230f19b4cd323a13029abff68f | |
parent | a70f3193e50f8fe4524bf2ff4666c4265521218d (diff) |
Revert to upstream DDE cli_sti code, with __thread
Flags in Linux and L4 are a per-processor thing. In userland, that simply maps
to a per-thread thing. Using a lock instead introduces deadlocks.
-rw-r--r-- | libdde_linux26/include/linux/spinlock.h | 19 | ||||
-rw-r--r-- | libdde_linux26/lib/src/arch/l4/cli_sti.c | 85 |
2 files changed, 12 insertions, 92 deletions
diff --git a/libdde_linux26/include/linux/spinlock.h b/libdde_linux26/include/linux/spinlock.h index 6830752b..ab862f99 100644 --- a/libdde_linux26/include/linux/spinlock.h +++ b/libdde_linux26/include/linux/spinlock.h @@ -372,10 +372,6 @@ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock); #else /* DDE_LINUX */ -unsigned long fake_local_irq_disable_flags(void); -void fake_local_irq_enable(void); -void fake_local_irq_restore(unsigned long flags); - #define spin_lock_init(l) \ do { \ ddekit_lock_init(&(l)->ddekit_lock); \ @@ -398,7 +394,7 @@ void fake_local_irq_restore(unsigned long flags); #define read_lock(lock) spin_lock(lock) #define write_lock(lock) spin_lock(lock) -#define spin_lock_irq(lock) fake_local_irq_disable_flags(); spin_lock(lock) +#define spin_lock_irq(lock) local_irq_disable(); spin_lock(lock) #define spin_lock_bh(lock) spin_lock(lock) #define read_lock_irq(lock) spin_lock_irq(lock) #define read_lock_bh(lock) spin_lock_bh(lock) @@ -415,7 +411,7 @@ void fake_local_irq_restore(unsigned long flags); #define read_unlock(lock) spin_unlock(lock) #define write_unlock(lock) spin_unlock(lock) -#define spin_unlock_irq(lock) spin_unlock(lock); fake_local_irq_enable() +#define spin_unlock_irq(lock) spin_unlock(lock); local_irq_enable() #define spin_unlock_bh(lock) spin_unlock(lock) #define read_unlock_irq(lock) spin_unlock_irq(lock) #define read_unlock_bh(lock) spin_unlock_bh(lock) @@ -424,7 +420,7 @@ void fake_local_irq_restore(unsigned long flags); #define spin_lock_irqsave(lock, flags) \ do { \ - flags = fake_local_irq_disable_flags(); \ + local_irq_save(flags); \ spin_lock(lock);\ } while (0); @@ -434,7 +430,7 @@ void fake_local_irq_restore(unsigned long flags); #define spin_unlock_irqrestore(lock, flags) \ do { \ spin_unlock(lock); \ - fake_local_irq_restore (flags); \ + local_irq_restore(flags); \ } while (0); #define read_unlock_irqrestore(lock, flags) spin_unlock_irqrestore(lock, flags) @@ -450,7 +446,12 @@ static int __lockfunc spin_trylock(spinlock_t *lock) #define _raw_spin_unlock(l) spin_unlock(l) #define _raw_spin_trylock(l) spin_trylock(l) -#define spin_trylock_irqsave(lock, flags) spin_trylock(lock) +#define spin_trylock_irqsave(lock, flags) \ +({ \ + local_irq_save(flags); \ + spin_trylock(lock) ? \ + 1 : ({ local_irq_restore(flags); 0; }); \ +}) #define read_trylock(l) spin_trylock(l) #define write_trylock(l) read_trylock(l) diff --git a/libdde_linux26/lib/src/arch/l4/cli_sti.c b/libdde_linux26/lib/src/arch/l4/cli_sti.c index e55e6401..81864ebb 100644 --- a/libdde_linux26/lib/src/arch/l4/cli_sti.c +++ b/libdde_linux26/lib/src/arch/l4/cli_sti.c @@ -3,10 +3,7 @@ #include <linux/kernel.h> /* IRQ lock reference counter */ -static atomic_t _refcnt = ATOMIC_INIT(0); -/* Refcnt value at which unlocking the cli_lock (it's not always 0) */ -static int unlock_refcnt; -static ddekit_lock_t cli_lock; +static __thread atomic_t _refcnt = ATOMIC_INIT(0); /* Check whether IRQs are currently disabled. * @@ -18,109 +15,31 @@ int raw_irqs_disabled_flags(unsigned long flags) return ((int)flags > 0); } -/* If it does lock operation successfully, return > 0. Otherwise, 0. */ -static int nested_lock(ddekit_lock_t lock) -{ - int do_lock = 0; - - if (ddekit_lock_try_lock(&lock)) { /* if we cannot lock */ - /* check who hold the lock. */ - if (_ddekit_lock_owner(&lock) != (int) ddekit_thread_myself()) { - /* Someone else holds the lock, - * or by the time I try to lock again, - * the person has release the lock. */ - ddekit_lock_lock(&lock); - do_lock = 1; - } - /* If I hold the lock myself, I don't need to worry - * the lock will be released somewhere before I do it. */ - } - else - do_lock = 2; - - return do_lock; -} - -unsigned long fake_local_irq_disable_flags(void) -{ - return atomic_add_return (1, &_refcnt) - 1; -} - -void fake_local_irq_enable(void) -{ - atomic_set(&_refcnt, 0); -} - -void fake_local_irq_restore(unsigned long flags) -{ - atomic_set(&_refcnt, flags); -} - /* Store the current flags state. * * This is done by returning the current refcnt. */ unsigned long __raw_local_save_flags(void) { - unsigned long flags; - int do_lock = 0; - - if (cli_lock == NULL) - ddekit_lock_init_unlocked(&cli_lock); - /* It's important to do lock here. - * Otherwise, a thread might not get correct flags. */ - do_lock = nested_lock(cli_lock); - flags = (unsigned long)atomic_read(&_refcnt); - if (do_lock) - ddekit_lock_unlock(&cli_lock); - return flags; + return (unsigned long)atomic_read(&_refcnt); } /* Restore IRQ state. */ void raw_local_irq_restore(unsigned long flags) { - Assert(cli_lock != NULL); atomic_set(&_refcnt, flags); - if (flags == unlock_refcnt) { - ddekit_lock_unlock(&cli_lock); - unlock_refcnt = 0; - } } /* Disable IRQs by grabbing the IRQ lock. */ void raw_local_irq_disable(void) { - struct ddekit_thread *helder; - int is_print = 0; - - if (cli_lock == NULL) - ddekit_lock_init_unlocked(&cli_lock); - - if (nested_lock(cli_lock)) { - /* Tell the corresponding restorer to release cli_lock, - * but do not update the value if there has been a re-enable in - * between, that would store a bogus value. - * XXX: scenario that will still break: - * save - * disable - * enable - * save - * disable - * restore - * restore - */ - if (unlock_refcnt < atomic_read(&_refcnt)) - unlock_refcnt = atomic_read(&_refcnt); - } atomic_inc(&_refcnt); } /* Unlock the IRQ lock until refcnt is 0. */ void raw_local_irq_enable(void) { - Assert(cli_lock != NULL); atomic_set(&_refcnt, 0); - ddekit_lock_unlock(&cli_lock); } |