diff options
author | jhb <jhb@FreeBSD.org> | 2001-08-21 18:42:45 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-08-21 18:42:45 +0000 |
commit | 4f6c3a9342d37bdb0df211e35041376b49f7a84c (patch) | |
tree | 816f3f94107ba741a2226b2601f4d608094894b4 /sys/kern/kern_synch.c | |
parent | fbda0f8d3ba2dd9cecf9c63819e8cd9f6c8c3ef3 (diff) | |
download | FreeBSD-src-4f6c3a9342d37bdb0df211e35041376b49f7a84c.zip FreeBSD-src-4f6c3a9342d37bdb0df211e35041376b49f7a84c.tar.gz |
- Fix a bug in the previous workaround for the tsleep/endtsleep race.
callout_stop() would fail in two cases:
1) The timeout was currently executing, and
2) The timeout had already executed.
We only needed to work around the race for 1). We caught some instances
of 2) via the PS_TIMEOUT flag, however, if endtsleep() fired after the
process had been woken up but before it had resumed execution,
PS_TIMEOUT would not be set, but callout_stop() would fail, so we
would block the process until endtsleep() resumed it. Except that
endtsleep() had already run and couldn't resume it. This adds a new flag
PS_TIMOFAIL to indicate the case of 2) when PS_TIMEOUT isn't set.
- Implement this race fix for condition variables as well.
Tested by: sos
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r-- | sys/kern/kern_synch.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 813bec1..6a20e10 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -451,7 +451,9 @@ msleep(ident, mtx, priority, wmesg, timo) p->p_sflag &= ~PS_TIMEOUT; if (sig == 0) rval = EWOULDBLOCK; - } else if (timo && callout_stop(&p->p_slpcallout) == 0) { + } else if (p->p_sflag & PS_TIMOFAIL) + p->p_sflag &= ~PS_TIMOFAIL; + else if (timo && callout_stop(&p->p_slpcallout) == 0) { /* * This isn't supposed to be pretty. If we are here, then * the endtsleep() callout is currently executing on another @@ -524,7 +526,8 @@ endtsleep(arg) else unsleep(p); p->p_sflag |= PS_TIMEOUT; - } + } else + p->p_sflag |= PS_TIMOFAIL; mtx_unlock_spin(&sched_lock); } |