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/sys_generic.c | |
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/sys_generic.c')
-rw-r--r-- | sys/kern/sys_generic.c | 56 |
1 files changed, 36 insertions, 20 deletions
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 |