From: Oren Laadan <orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
To: Oren Laadan <orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Subject: Re: [PATCH 4/4] c/r: support for real/virt/prof itimers (v2)
Date: Tue, 04 Aug 2009 14:43:54 -0400 [thread overview]
Message-ID: <4A78816A.6080001@librato.com> (raw)
In-Reply-To: <20090804141746.GQ29252-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
Louis Rilling wrote:
> Hi Oren,
>
> On 04/08/09 5:09 -0400, Oren Laadan wrote:
>> This patch adds support for real/virt/prof itimers.
>> Expiry and the interval values are both saved in nanoseconds.
>>
>> Signed-off-by: Oren Laadan <orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
>> ---
>> checkpoint/signal.c | 72 ++++++++++++++++++++++++++++++++++++++++
>> include/linux/checkpoint_hdr.h | 6 +++
>> 2 files changed, 78 insertions(+), 0 deletions(-)
>>
>> diff --git a/checkpoint/signal.c b/checkpoint/signal.c
>> index c9da06b..18b3e2d 100644
>> --- a/checkpoint/signal.c
>> +++ b/checkpoint/signal.c
>> @@ -15,6 +15,7 @@
>> #include <linux/signal.h>
>> #include <linux/errno.h>
>> #include <linux/resource.h>
>> +#include <linux/timer.h>
>> #include <linux/checkpoint.h>
>> #include <linux/checkpoint_hdr.h>
>>
>> @@ -264,6 +265,7 @@ static int checkpoint_signal(struct ckpt_ctx *ctx, struct task_struct *t)
>> struct signal_struct *signal;
>> struct sigpending shared_pending;
>> struct rlimit *rlim;
>> + struct timeval tval;
>> unsigned long flags;
>> int i, ret;
>>
>> @@ -299,6 +301,49 @@ static int checkpoint_signal(struct ckpt_ctx *ctx, struct task_struct *t)
>> h->rlim[i].rlim_cur = rlim[i].rlim_cur;
>> h->rlim[i].rlim_max = rlim[i].rlim_max;
>> }
>> +
>> + /* real/virt/prof itimers */
>> + h->it_real_incr = ktime_to_ns(signal->it_real_incr);
>> + /*
>> + * (a) If the timer is now active (did not expire), compute
>> + * the time delta.
>> + * (b) If the timer expired, and delivered the signal already,
>> + * then set the expire (value) to the interval
>> + * (c) If the timer expired but did not yet deliver the
>> + * signal, then set the expire to the minimum possible, so it
>> + * will expire immediately after restart succeeds.
>> + */
>> + if (hrtimer_active(&signal->real_timer)) {
>> + ktime_t delta = hrtimer_get_remaining(&signal->real_timer);
>> + /*
>> + * If the timer expired after the the test above, then
>> + * set the expire to the minimum possible (because by
>> + * now the pending signals have been saved already, but
>> + * without the signal from this very expiry).
>> + */
>> + ckpt_debug("active ! %lld\n", delta.tv64);
>> + if (delta.tv64 <= 0)
>> + delta.tv64 = NSEC_PER_USEC;
>> + h->it_real_value = ktime_to_ns(delta);
>> + } else if (sigismember(&signal->shared_pending.signal, SIGALRM)) {
>> + /* case (b) */
>> + h->it_real_value = h->it_real_incr;
>> + } else {
>> + /* case (c) */
>> + h->it_real_value =
>> + ktime_to_ns((ktime_t) { .tv64 = NSEC_PER_USEC });
>> + }
>
> AFAICS the third case catches expired timers having not delivered the signal yet
> as well as inactive timers. If the latter, at restart the timer will be
> rearmed while it should not.
>
> However, reading hrtimer code I understand that case (c) cannot happen. IOW if
> the timer has expired but has not sent SIGALRM yet, then hrtimer_active()
> returns true, and the first block already handles that case correctly.
Yes, I re-read the code and (c) should not happen, because the timer
cannot become inactive without having sent SIGALRM as long as we hold
the siglock.
> Moreover case (b) only happens if the timer was not automatically rearmed,
> that is it_real_incr == 0. So in this case the signal was already sent (and
> picked for checkpointing if not handled), and h->it_real_value should be set to
> 0.
Here is the scenario I had in mind:
1) kernel/hrtimer.c:__run_hrtimer() is called with the timer fires,
sets the timer state to HRTIMER_STATE_CALLBACK and then invokes
the callback.
2) for itimers, the callback is kernel/itimer.c:it_real_fn(): it
sends the signal and returns HRTIMER_NORESTART.
3) back to __run_hrtimer() which does _not_ call enqueue_hrtimer(),
and then _clears_ the HRTIMER_STATE_CALLBACK. This results in the
state being zero -- that is, hrtimer_active() will be false.
So in #2 SIGALRM was sent, and then in #3 the timer became inactive
without holding siglock, and not re-armed. (if it_real_incr > 0, it
should and will be re-armed when the signal is dequeued).
Therefore when we restart, we need to set it_real_incr to its saved
value, and it_real_value to 0. Then, if SIGALRM was sent, it will
be dequeued after restart, and depending on it_real_incr the timer
will, or will not, be re-armed. If SIGALRM was not sent, then it
must be that it_real_incr is also 0.
IOW, in both cases (SIGALRM sent/not sent) of the inactive timer,
the value of it_real_incr should be 0, therefore the code you
suggest below is correct, except for the BUG_ON statement.
(In restart, it's not a big deal if these values are "incorrect",
because the worst harm it can do is send a superfluous SIGALRM).
>
> So the following could be actually better:
>
> h->it_real_incr = ktime_to_ns(signal->it_real_incr);
> /*
> * (a) If the timer is now active, compute the time delta.
> * (b) Otherwise, siglock ensures that */
> if (hrtimer_active(&signal->real_timer)) {
> ktime_t delta = hrtimer_get_remaining(&signal->real_timer);
> /*
> * If the timer expired after the the test above, then
> * set the expire to the minimum possible (because by
> * now the pending signals have been saved already, but
> * the signal from this very expiry won't be sent before we
> * release t->sighand->siglock.
> */
> ckpt_debug("active ! %lld\n", delta.tv64);
> if (delta.tv64 <= 0)
> delta.tv64 = NSEC_PER_USEC;
> h->it_real_value = ktime_to_ns(delta);
> } else {
> BUG_ON(h->it_real_incr);
> h->it_real_value = 0;
> }
>
> Louis
Thanks,
Oren.
next prev parent reply other threads:[~2009-08-04 18:43 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-04 9:09 c/r: support for pending signals (v2) Oren Laadan
[not found] ` <1249376956-27555-1-git-send-email-orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
2009-08-04 9:09 ` [PATCH 1/4] c/r: blocked and template for shared " Oren Laadan
2009-08-04 9:09 ` [PATCH 2/4] c/r: checkpoint/restart of rlimit (v2) Oren Laadan
2009-08-04 9:09 ` [PATCH 3/4] c/r: pending signals (private, shared) (v2) Oren Laadan
2009-08-04 9:09 ` [PATCH 4/4] c/r: support for real/virt/prof itimers (v2) Oren Laadan
[not found] ` <1249376956-27555-5-git-send-email-orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
2009-08-04 14:17 ` Louis Rilling
[not found] ` <20090804141746.GQ29252-Hu8+6S1rdjywhHL9vcZdMVaTQe2KTcn/@public.gmane.org>
2009-08-04 18:43 ` Oren Laadan [this message]
[not found] ` <4A78816A.6080001-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
2009-08-05 10:40 ` Louis Rilling
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A78816A.6080001@librato.com \
--to=orenl-rdfvbdnroixbdgjk7y7tuq@public.gmane.org \
--cc=containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.