Hi Ingo,

I am trying to fix the BUG I mentioned here: 
http://lkml.org/lkml/2007/04/20/41. The problem arises because 
ptrace_attach() calls local_irq_disable() and write_trylock() and later calls 
write_unlock_irq. On -rt write_unlock_irq doesn't restore irqs for regular 
rwlock_t, so irqs remain disabled. I have also sent patches for mainline 
kernel. Please refer http://lkml.org/lkml/2007/05/09/76 , 
http://lkml.org/lkml/2007/05/09/79 and http://lkml.org/lkml/2007/05/09/550

This patch adds write_trylock_irqsave function.

Signed-off-by: Sripathi Kodi <[EMAIL PROTECTED]>

Index: linux-2.6.21-rt1_patch/include/linux/spinlock.h
===================================================================
--- linux-2.6.21-rt1_patch.orig/include/linux/spinlock.h        2007-05-10 
11:28:35.000000000 +0530
+++ linux-2.6.21-rt1_patch/include/linux/spinlock.h     2007-05-10 
11:29:13.000000000 +0530
@@ -323,6 +323,7 @@
 
 # define _read_trylock(rwl)    rt_read_trylock(rwl)
 # define _write_trylock(rwl)   rt_write_trylock(rwl)
+#define _write_trylock_irqsave(rwl, flags)  rt_write_trylock_irqsave(rwl, 
flags)
 
 # define _read_lock(rwl)       rt_read_lock(rwl)
 # define _write_lock(rwl)      rt_write_lock(rwl)
@@ -398,6 +399,19 @@
        else __bad_rwlock_type();                                       \
 } while (0)
 
+#define PICK_RW_OP2_RET(optype, op, lock, flags)                       \
+({                                                                     \
+       unsigned long __ret;                                            \
+                                                                       \
+       if (TYPE_EQUAL((lock), raw_rwlock_t))                           \
+               __ret = __##optype##op((raw_rwlock_t *)(lock), flags);  \
+       else if (TYPE_EQUAL(lock, rwlock_t))                            \
+               __ret = _##optype##op((rwlock_t *)(lock), flags);       \
+       else __bad_rwlock_type();                                       \
+                                                                       \
+       __ret;                                                          \
+})
+
 #ifdef CONFIG_DEBUG_SPINLOCK
   extern void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
                                   struct lock_class_key *key);
@@ -473,6 +487,9 @@
 //#define write_trylock(lock)  _write_trylock(lock)
 #define write_trylock(lock)    __cond_lock(lock, PICK_RW_OP_RET(write, 
_trylock, 
lock))
 
+#define write_trylock_irqsave(lock, flags) \
+       __cond_lock(lock, PICK_RW_OP2_RET(write, _trylock_irqsave, lock, 
&flags))
+
 #define __spin_can_lock(lock)  __raw_spin_can_lock(&(lock)->raw_lock)
 #define __read_can_lock(lock)  __raw_read_can_lock(&(lock)->raw_lock)
 #define __write_can_lock(lock) __raw_write_can_lock(&(lock)->raw_lock)
Index: linux-2.6.21-rt1_patch/include/linux/spinlock_api_smp.h
===================================================================
--- linux-2.6.21-rt1_patch.orig/include/linux/spinlock_api_smp.h        
2007-05-10 
11:28:35.000000000 +0530
+++ linux-2.6.21-rt1_patch/include/linux/spinlock_api_smp.h     2007-05-10 
11:29:13.000000000 +0530
@@ -48,6 +48,8 @@
 __spin_trylock_irqsave(raw_spinlock_t *lock, unsigned long *flags);
 int __lockfunc __read_trylock(raw_rwlock_t *lock);
 int __lockfunc __write_trylock(raw_rwlock_t *lock);
+int __lockfunc
+__write_trylock_irqsave(raw_rwlock_t *lock, unsigned long *flags);
 int __lockfunc __spin_trylock_bh(raw_spinlock_t *lock);
 int __lockfunc __spin_trylock_irq(raw_spinlock_t *lock);
 void __lockfunc __spin_unlock(raw_spinlock_t *lock)            RELEASE_SPIN;
Index: linux-2.6.21-rt1_patch/include/linux/spinlock_api_up.h
===================================================================
--- linux-2.6.21-rt1_patch.orig/include/linux/spinlock_api_up.h 2007-05-10 
11:28:35.000000000 +0530
+++ linux-2.6.21-rt1_patch/include/linux/spinlock_api_up.h      2007-05-10 
11:29:13.000000000 +0530
@@ -41,6 +41,8 @@
 
 #define __spin_trylock_irqsave(lock, flags)    __TRYLOCK_IRQSAVE(lock, flags)
 
+#define __write_trylock_irqsave(lock, flags)   __TRYLOCK_IRQSAVE(lock, flags)
+
 #define __UNLOCK(lock) \
   do { preempt_enable(); __release(lock); (void)(lock); } while (0)
 
Index: linux-2.6.21-rt1_patch/kernel/rt.c
===================================================================
--- linux-2.6.21-rt1_patch.orig/kernel/rt.c     2007-05-10 11:28:35.000000000 
+0530
+++ linux-2.6.21-rt1_patch/kernel/rt.c  2007-05-10 11:29:13.000000000 +0530
@@ -173,6 +173,12 @@
 }
 EXPORT_SYMBOL(rt_write_trylock);
 
+int __lockfunc rt_write_trylock_irqsave(rwlock_t *rwlock, unsigned long 
*flags)
+{
+       *flags = 0;
+       return rt_write_trylock(rwlock);
+}
+
 int __lockfunc rt_read_trylock(rwlock_t *rwlock)
 {
        struct rt_mutex *lock = &rwlock->lock;
Index: linux-2.6.21-rt1_patch/kernel/spinlock.c
===================================================================
--- linux-2.6.21-rt1_patch.orig/kernel/spinlock.c       2007-05-10 
11:28:35.000000000 +0530
+++ linux-2.6.21-rt1_patch/kernel/spinlock.c    2007-05-10 11:29:13.000000000 
+0530
@@ -97,6 +97,20 @@
 }
 EXPORT_SYMBOL(__write_trylock);
 
+int __lockfunc __write_trylock_irqsave(raw_rwlock_t *lock, unsigned long 
*flags)
+{
+       int ret;
+
+       local_irq_save(*flags);
+       ret = __write_trylock(lock);
+       if (ret)
+               return ret;
+
+       local_irq_restore(*flags);
+       return 0;
+}
+EXPORT_SYMBOL(__write_trylock_irqsave);
+
 /*
  * If lockdep is enabled then we use the non-preemption spin-ops
  * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to