Messages in this thread Patch in this message | | | Date | Tue, 18 May 1999 23:40:20 +1000 | From | Richard Gooch <> | Subject | [PATCH] Improving send_sigio() scalability |
| |
Alexander Kjeldaas writes: > On Mon, May 17, 1999 at 01:17:59PM +1000, Richard Gooch wrote: > > Hi, all. I just noticed that send_sigio() walks the task list, > > looking for the process(es) to send a signal to. This appears to be a > > potential scalability problem, as a large number of tasks is going to > > slow this down. > > > > Has anyone done any benchmarking to evaluate the effect of this? In > > the absence of numbers, how about some convincing handwaving? Is it > > worth exploring options to fix this? > > > > I can think of one quick and simple hack to fix this for 90% (maybe > > 99%) of cases: record the task pointer at fcntl() time. Then at > > send_sigio() time, if the recorded pid and task match, skip the > > task list walk. > > In the case where send_sigio is sending a signal to a specific > process, why isn't it using find_task_by_pid()?.
As promised, here's the patch to do this. Not only is it good (it compiles), but it is perfect (it boots). Up 9 minutes so far without problems.
Regards,
Richard....
diff -urN linux-2.3.3/fs/fcntl.c linux/fs/fcntl.c --- linux-2.3.3/fs/fcntl.c Sat Nov 14 05:07:26 1998 +++ linux/fs/fcntl.c Tue May 18 23:21:47 1999 @@ -183,26 +183,15 @@ return err; } -static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa) +static void send_sigio_to_task(struct task_struct *p, + struct fown_struct *fown, struct fasync_struct *fa) { - struct task_struct * p; - int pid = fown->pid; - uid_t uid = fown->uid; - uid_t euid = fown->euid; - - read_lock(&tasklist_lock); - for_each_task(p) { - int match = p->pid; - if (pid < 0) - match = -p->pgrp; - if (pid != match) - continue; - if ((euid != 0) && - (euid ^ p->suid) && (euid ^ p->uid) && - (uid ^ p->suid) && (uid ^ p->uid)) - continue; - switch (fown->signum) { - siginfo_t si; + if ((fown->euid != 0) && + (fown->euid ^ p->suid) && (fown->euid ^ p->uid) && + (fown->uid ^ p->suid) && (fown->uid ^ p->uid)) + return; + switch (fown->signum) { + siginfo_t si; default: /* Queue a rt signal with the appropriate fd as its value. We use SI_SIGIO as the source, not @@ -213,16 +202,36 @@ si.si_signo = fown->signum; si.si_errno = 0; si.si_code = SI_SIGIO; - si.si_pid = pid; - si.si_uid = uid; + si.si_pid = fown->pid; + si.si_uid = fown->uid; si.si_fd = fa->fa_fd; if (!send_sig_info(fown->signum, &si, p)) break; /* fall-through: fall back on the old plain SIGIO signal */ case 0: send_sig(SIGIO, p, 1); - } } +} + +static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa) +{ + struct task_struct * p; + int pid = fown->pid; + + read_lock(&tasklist_lock); + if ( (pid > 0) && (p = find_task_by_pid(pid)) ) { + send_sigio_to_task(p, fown, fa); + goto out; + } + for_each_task(p) { + int match = p->pid; + if (pid < 0) + match = -p->pgrp; + if (pid != match) + continue; + send_sigio_to_task(p, fown, fa); + } +out: read_unlock(&tasklist_lock); } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |