From 4057679b76ae5e1f7e79802be8399396f29c0b09 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 7 Apr 2012 22:04:12 +0000 Subject: 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. --- libdde_linux26/include/linux/spinlock.h | 19 +++---- 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 /* 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); } -- cgit v1.2.3 From 269dd0992a850c9d1a28e636977c4a4955a33212 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 7 Apr 2012 23:18:52 +0000 Subject: Do not enable irqs during softirq processing, just like upstream DDE --- libdde_linux26/lib/src/arch/l4/softirq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libdde_linux26/lib/src/arch/l4/softirq.c b/libdde_linux26/lib/src/arch/l4/softirq.c index 67e8f5aa..21b36d17 100644 --- a/libdde_linux26/lib/src/arch/l4/softirq.c +++ b/libdde_linux26/lib/src/arch/l4/softirq.c @@ -172,6 +172,7 @@ static void tasklet_hi_action(struct softirq_action *a) } } + #define MAX_SOFTIRQ_RETRIES 10 /** Run softirq handlers @@ -185,7 +186,6 @@ void __do_softirq(void) /* reset softirq count */ set_softirq_pending(0); - local_irq_enable(); /* While we have a softirq pending... */ while (pending) { @@ -197,7 +197,6 @@ void __do_softirq(void) /* remove pending flag for last softirq */ pending >>= 1; } - local_irq_disable(); /* Somebody might have scheduled another softirq in between * (e.g., an IRQ thread or another tasklet). */ -- cgit v1.2.3