diff options
author | Bryan Cantrill <bryan@joyent.com> | 2015-09-08 07:59:32 +0000 |
---|---|---|
committer | Bryan Cantrill <bryan@joyent.com> | 2015-09-08 07:59:32 +0000 |
commit | f02d4dd3ff080329f0cb01b63fef17bb6a72c06b (patch) | |
tree | dd22038a154ad7bb9f0372cc204b373cf1f152c5 /usr/src | |
parent | 776df8cd0f399e238b36d4e075fc9e49be5188bf (diff) | |
download | illumos-joyent-f02d4dd3ff080329f0cb01b63fef17bb6a72c06b.tar.gz |
OS-4713 timerfd_settime(3C) should clear tfd_fired
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/timerfd.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/timerfd.c b/usr/src/uts/common/io/timerfd.c index 2f59c0f3e2..65c7d6b30b 100644 --- a/usr/src/uts/common/io/timerfd.c +++ b/usr/src/uts/common/io/timerfd.c @@ -340,6 +340,34 @@ timerfd_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) } } + /* + * Before we set the time, we're going to clear tfd_fired. + * This can potentially race with the (old) timer firing, but + * the window is deceptively difficult to close: if we were + * to simply clear tfd_fired after the call to the backend + * returned, we would run the risk of plowing a firing of the + * new timer. Ultimately, the race can only be resolved by + * the backend, which would likely need to be extended with a + * function to call back into when the timer is between states + * (that is, after the timer can no longer fire with the old + * timer value, but before it can fire with the new one). + * This is straightforward enough for backends that set a + * timer's value by deleting the old one and adding the new + * one, but for those that modify the timer value in place + * (e.g., cyclics), the required serialization is necessarily + * delicate: the function would have to be callable from + * arbitrary interrupt context. While implementing all of + * this is possible, it does not (for the moment) seem worth + * it: if the timer is firing at essentially the same moment + * that it's being reprogrammed, there is a higher-level race + * with respect to timerfd usage that the progam itself will + * have to properly resolve -- and it seems reasonable to + * simply allow the program to resolve it in this case. + */ + mutex_enter(&state->tfd_lock); + state->tfd_fired = 0; + mutex_exit(&state->tfd_lock); + err = it->it_backend->clk_timer_settime(it, st.tfd_settime_flags & TFD_TIMER_ABSTIME ? TIMER_ABSTIME : TIMER_RELTIME, &when); |