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.
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);