--- arch/x86/kernel/entry_64.S | 7 ++----- include/linux/rwsem-spinlock.h | 4 ++-- include/linux/rwsem.h | 12 ++++++++++++ kernel/rwsem.c | 23 +++++++++++++++++++++-- lib/rwsem-spinlock.c | 14 +++++++------- 5 files changed, 44 insertions(+), 16 deletions(-) Index: linux-2.6/include/linux/rwsem.h =================================================================== --- linux-2.6.orig/include/linux/rwsem.h 2008-06-17 09:29:24.527635710 -0700 +++ linux-2.6/include/linux/rwsem.h 2008-06-17 16:41:10.328885966 -0700 @@ -48,11 +48,23 @@ extern int down_write_trylock(struct rw_ extern void up_read(struct rw_semaphore *sem); /* + * Release a read lock but do not run pending writers / readers + * immediately. + */ +extern void up_read_async(struct rw_semaphore *sem); + +/* * release a write lock */ extern void up_write(struct rw_semaphore *sem); /* + * Release a write lock but do not run pending writers / readers + * immediately. + */ +extern void up_write_async(struct rw_semaphore *sem); + +/* * downgrade write lock to read lock */ extern void downgrade_write(struct rw_semaphore *sem); Index: linux-2.6/kernel/rwsem.c =================================================================== --- linux-2.6.orig/kernel/rwsem.c 2008-06-17 09:29:24.557625153 -0700 +++ linux-2.6/kernel/rwsem.c 2008-06-17 16:55:28.268886003 -0700 @@ -74,11 +74,21 @@ void up_read(struct rw_semaphore *sem) { rwsem_release(&sem->dep_map, 1, _RET_IP_); - __up_read(sem); + __up_read(sem, 0); } EXPORT_SYMBOL(up_read); +void up_read_async(struct rw_semaphore *sem) +{ + rwsem_release(&sem->dep_map, 1, _RET_IP_); + + __up_read(sem, 1); +} + +EXPORT_SYMBOL(up_read_async); + + /* * release a write lock */ @@ -86,11 +96,20 @@ void up_write(struct rw_semaphore *sem) { rwsem_release(&sem->dep_map, 1, _RET_IP_); - __up_write(sem); + __up_write(sem, 0); } EXPORT_SYMBOL(up_write); +void up_write_async(struct rw_semaphore *sem) +{ + rwsem_release(&sem->dep_map, 1, _RET_IP_); + + __up_write(sem, 0); +} + +EXPORT_SYMBOL(up_write_async); + /* * downgrade write lock to read lock */ Index: linux-2.6/include/linux/rwsem-spinlock.h =================================================================== --- linux-2.6.orig/include/linux/rwsem-spinlock.h 2008-06-17 09:29:24.547626416 -0700 +++ linux-2.6/include/linux/rwsem-spinlock.h 2008-06-17 16:41:10.356385685 -0700 @@ -65,8 +65,8 @@ extern int __down_read_trylock(struct rw extern void __down_write(struct rw_semaphore *sem); extern void __down_write_nested(struct rw_semaphore *sem, int subclass); extern int __down_write_trylock(struct rw_semaphore *sem); -extern void __up_read(struct rw_semaphore *sem); -extern void __up_write(struct rw_semaphore *sem); +extern void __up_read(struct rw_semaphore *sem, int async); +extern void __up_write(struct rw_semaphore *sem, int async); extern void __downgrade_write(struct rw_semaphore *sem); static inline int rwsem_is_locked(struct rw_semaphore *sem) Index: linux-2.6/lib/rwsem-spinlock.c =================================================================== --- linux-2.6.orig/lib/rwsem-spinlock.c 2008-06-17 09:29:24.567626697 -0700 +++ linux-2.6/lib/rwsem-spinlock.c 2008-06-17 16:59:13.628885353 -0700 @@ -45,7 +45,7 @@ void __init_rwsem(struct rw_semaphore *s * - writers are only woken if wakewrite is non-zero */ static inline struct rw_semaphore * -__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) +__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite, int async) { struct rwsem_waiter *waiter; struct task_struct *tsk; @@ -104,7 +104,7 @@ __rwsem_do_wake(struct rw_semaphore *sem * wake a single writer */ static inline struct rw_semaphore * -__rwsem_wake_one_writer(struct rw_semaphore *sem) +__rwsem_wake_one_writer(struct rw_semaphore *sem, int async) { struct rwsem_waiter *waiter; struct task_struct *tsk; @@ -260,14 +260,14 @@ int __down_write_trylock(struct rw_semap /* * release a read lock on the semaphore */ -void __up_read(struct rw_semaphore *sem) +void __up_read(struct rw_semaphore *sem, int async) { unsigned long flags; spin_lock_irqsave(&sem->wait_lock, flags); if (--sem->activity == 0 && !list_empty(&sem->wait_list)) - sem = __rwsem_wake_one_writer(sem); + sem = __rwsem_wake_one_writer(sem, async); spin_unlock_irqrestore(&sem->wait_lock, flags); } @@ -275,7 +275,7 @@ void __up_read(struct rw_semaphore *sem) /* * release a write lock on the semaphore */ -void __up_write(struct rw_semaphore *sem) +void __up_write(struct rw_semaphore *sem, int async) { unsigned long flags; @@ -283,7 +283,7 @@ void __up_write(struct rw_semaphore *sem sem->activity = 0; if (!list_empty(&sem->wait_list)) - sem = __rwsem_do_wake(sem, 1); + sem = __rwsem_do_wake(sem, 1, async); spin_unlock_irqrestore(&sem->wait_lock, flags); } @@ -300,7 +300,7 @@ void __downgrade_write(struct rw_semapho sem->activity = 1; if (!list_empty(&sem->wait_list)) - sem = __rwsem_do_wake(sem, 0); + sem = __rwsem_do_wake(sem, 0, 0); spin_unlock_irqrestore(&sem->wait_lock, flags); } Index: linux-2.6/arch/x86/kernel/entry_64.S =================================================================== --- linux-2.6.orig/arch/x86/kernel/entry_64.S 2008-06-17 18:06:44.480136040 -0700 +++ linux-2.6/arch/x86/kernel/entry_64.S 2008-06-17 18:11:03.881774960 -0700 @@ -766,18 +766,15 @@ END(spurious_interrupt) SWAPGS xorl %ebx,%ebx 1: - .if \ist - movq %gs:pda_data_offset, %rbp - .endif movq %rsp,%rdi movq ORIG_RAX(%rsp),%rsi movq $-1,ORIG_RAX(%rsp) .if \ist - subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + subq $EXCEPTION_STKSZ, %gs:per_cpu__init_tss + TSS_ist + (\ist - 1) * 8 .endif call \sym .if \ist - addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + addq $EXCEPTION_STKSZ, %gs:per_cpu__init_tss + TSS_ist + (\ist - 1) * 8 .endif DISABLE_INTERRUPTS(CLBR_NONE) .if \irqtrace