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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox