diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2007-03-24 16:01:23 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2007-03-24 16:01:23 +0000 |
commit | b85e9ba20c14a428d67fc578018fd8a539c89f7b (patch) | |
tree | b40dafa9a5122b8fb1353291f58602e22cbd30a1 /sys/kern | |
parent | bb009c4c0bea668c35c72a9601e752153bc19d8a (diff) |
Kill the horrible hack of storing the pid in struct selinfo.
Instead, keep the proc pointer in it and put the selinfo on a list
in struct proc in selrecord. Then clean up the list when leaving
sys_select and sys_poll.
miod@ ok, testing by many, including Bobs spamd boxes.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_main.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 4 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 56 |
3 files changed, 42 insertions, 22 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index e41810455d8..291aa2e5a6a 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.136 2007/03/19 14:33:28 dlg Exp $ */ +/* $OpenBSD: init_main.c,v 1.137 2007/03/24 16:01:22 art Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -296,6 +296,8 @@ main(void *framep) /* Create the file descriptor table. */ p->p_fd = fdinit(NULL); + TAILQ_INIT(&p->p_selects); + /* Create the limits structures. */ p->p_limit = &limit0; for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index d19608d9cbc..da8d0df31c4 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.87 2007/03/15 10:22:30 art Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.88 2007/03/24 16:01:22 art Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -246,6 +246,8 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, p2->p_cred->p_refcnt = 1; crhold(p1->p_ucred); + TAILQ_INIT(&p2->p_selects); + /* bump references to the text vnode (for procfs) */ p2->p_textvp = p1->p_textvp; if (p2->p_textvp) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 31cbafefff7..a79c121c00c 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.55 2007/03/15 10:22:30 art Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.56 2007/03/24 16:01:22 art Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -66,6 +66,8 @@ int selscan(struct proc *, fd_set *, fd_set *, int, int, register_t *); int seltrue(dev_t, int, struct proc *); void pollscan(struct proc *, struct pollfd *, u_int, register_t *); +void sel_clean_proclist(struct proc *); + /* * Read system call. */ @@ -708,6 +710,7 @@ retry: if (error == 0) goto retry; done: + sel_clean_proclist(p); atomic_clearbits_int(&p->p_flag, P_SELECT); /* select is not restarted after signals... */ if (error == ERESTART) @@ -781,17 +784,12 @@ seltrue(dev_t dev, int events, struct proc *p) void selrecord(struct proc *selector, struct selinfo *sip) { - struct proc *p; - pid_t mypid; - - mypid = selector->p_pid; - if (sip->si_selpid == mypid) - return; - if (sip->si_selpid && (p = pfind(sip->si_selpid)) && - p->p_wchan == (caddr_t)&selwait) + if (sip->si_selproc == NULL) { + sip->si_selproc = selector; + TAILQ_INSERT_TAIL(&selector->p_selects, sip, si_list); + } else if (sip->si_selproc != selector) { sip->si_flags |= SI_COLL; - else - sip->si_selpid = mypid; + } } /* @@ -803,25 +801,42 @@ selwakeup(struct selinfo *sip) struct proc *p; int s; - if (sip->si_selpid == 0) - return; if (sip->si_flags & SI_COLL) { nselcoll++; sip->si_flags &= ~SI_COLL; wakeup(&selwait); } - p = pfind(sip->si_selpid); - sip->si_selpid = 0; - if (p != NULL) { - SCHED_LOCK(s); - if (p->p_wchan == (caddr_t)&selwait) { + + /* + * We check the process once before locking. + * Then we wake the process and clean up its + * selects list. + */ + if (sip->si_selproc == NULL) + return; + + SCHED_LOCK(s); + if ((p = sip->si_selproc) != NULL) { + if (p->p_wchan != NULL) { if (p->p_stat == SSLEEP) setrunnable(p); else unsleep(p); - } else if (p->p_flag & P_SELECT) + } else { atomic_clearbits_int(&p->p_flag, P_SELECT); - SCHED_UNLOCK(s); + } + } + SCHED_UNLOCK(s); +} + +void +sel_clean_proclist(struct proc *p) +{ + struct selinfo *sip; + + while ((sip = TAILQ_FIRST(&p->p_selects)) != NULL) { + sip->si_selproc = NULL; + TAILQ_REMOVE(&p->p_selects, sip, si_list); } } @@ -932,6 +947,7 @@ retry: goto retry; done: + sel_clean_proclist(p); atomic_clearbits_int(&p->p_flag, P_SELECT); /* * NOTE: poll(2) is not restarted after a signal and EWOULDBLOCK is |