diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2007-07-25 23:11:54 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2007-07-25 23:11:54 +0000 |
commit | 070039b1c8ca03061ac4202b16fd7b3e290f5c02 (patch) | |
tree | f019791fc2b31cd7da6831063764dce783a8677e /sys/kern/sys_generic.c | |
parent | 2a06794e0449288c91c5fbccd8dfe13c4cacf9d9 (diff) |
Back out the tracking of procs in struct selinfo. There's one serious
bug in the code, but as soon as I try to fix it, it seems to trigger
some other bugs. Instead of trying to figure out what's going on
while everyone suffers, it's better to back out and figure out
the bugs outside the tree.
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r-- | sys/kern/sys_generic.c | 56 |
1 files changed, 20 insertions, 36 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index a79c121c00c..f68f5251a7d 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.56 2007/03/24 16:01:22 art Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.57 2007/07/25 23:11:52 art Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -66,8 +66,6 @@ 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. */ @@ -710,7 +708,6 @@ 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) @@ -784,12 +781,17 @@ seltrue(dev_t dev, int events, struct proc *p) void selrecord(struct proc *selector, struct selinfo *sip) { - if (sip->si_selproc == NULL) { - sip->si_selproc = selector; - TAILQ_INSERT_TAIL(&selector->p_selects, sip, si_list); - } else if (sip->si_selproc != selector) { + 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) sip->si_flags |= SI_COLL; - } + else + sip->si_selpid = mypid; } /* @@ -801,42 +803,25 @@ 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); } - - /* - * 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) { + p = pfind(sip->si_selpid); + sip->si_selpid = 0; + if (p != NULL) { + SCHED_LOCK(s); + if (p->p_wchan == (caddr_t)&selwait) { if (p->p_stat == SSLEEP) setrunnable(p); else unsleep(p); - } else { + } else if (p->p_flag & P_SELECT) atomic_clearbits_int(&p->p_flag, P_SELECT); - } - } - 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); + SCHED_UNLOCK(s); } } @@ -947,7 +932,6 @@ 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 |