From: Manfred Spraul <manfred@colorfullife.com>

fasync_helper and kill_fasync are helpers for managing F_SETFL fcntl 
calls that change FASYNC and sending the necessary signals. The locking 
uses one global rwlock that's acquired for read in all kill_fasync 
calls, and that causes cache line trashing. This is not necessary: if 
the fasync list is empty, then there is no need to acquire the rwlock.
Tests with reaim on a 4-way pIII on STP showed an 80% reduction of the 
time within kill_fasync.



 fs/fcntl.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff -puN fs/fcntl.c~kill_fasync-speedup fs/fcntl.c
--- 25/fs/fcntl.c~kill_fasync-speedup	2003-12-30 13:13:27.000000000 -0800
+++ 25-akpm/fs/fcntl.c	2003-12-30 13:13:27.000000000 -0800
@@ -609,9 +609,15 @@ EXPORT_SYMBOL(__kill_fasync);
 
 void kill_fasync(struct fasync_struct **fp, int sig, int band)
 {
-	read_lock(&fasync_lock);
-	__kill_fasync(*fp, sig, band);
-	read_unlock(&fasync_lock);
+	/* First a quick test without locking: usually
+	 * the list is empty.
+	 */
+	if (*fp) {
+		read_lock(&fasync_lock);
+		/* reread *fp after obtaining the lock */
+		__kill_fasync(*fp, sig, band);
+		read_unlock(&fasync_lock);
+	}
 }
 
 EXPORT_SYMBOL(kill_fasync);

_