[Devel] [PATCH 4/4] c/r: support for real/virt/prof itimers (v2)
Oren Laadan
orenl at librato.com
Tue Aug 4 02:09:16 PDT 2009
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 at cs.columbia.edu>
---
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 });
+ }
+
+ cputime_to_timeval(signal->it_virt_expires, &tval);
+ h->it_virt_value = timeval_to_ns(&tval);
+ cputime_to_timeval(signal->it_virt_incr, &tval);
+ h->it_virt_incr = timeval_to_ns(&tval);
+
+ cputime_to_timeval(signal->it_prof_expires, &tval);
+ h->it_prof_value = timeval_to_ns(&tval);
+ cputime_to_timeval(signal->it_prof_incr, &tval);
+ h->it_prof_incr = timeval_to_ns(&tval);
+
unlock_task_sighand(t, &flags);
ret = ckpt_write_obj(ctx, &h->h);
@@ -416,6 +461,7 @@ static int restore_signal(struct ckpt_ctx *ctx)
struct ckpt_hdr_signal *h;
struct sigpending new_pending;
struct sigpending *pending;
+ struct itimerval itimer;
struct rlimit rlim;
int i, ret;
@@ -436,12 +482,38 @@ static int restore_signal(struct ckpt_ctx *ctx)
if (ret < 0)
goto out;
+ /*
+ * Reset real/virt/prof itimer (in case they were set), to
+ * prevent unwanted signals after flushing current signals
+ * and before restoring original real/virt/prof itimer.
+ */
+ itimer.it_value = (struct timeval) { .tv_sec = 0, .tv_usec = 0 };
+ itimer.it_interval = (struct timeval) { .tv_sec = 0, .tv_usec = 0 };
+ do_setitimer(ITIMER_REAL, &itimer, NULL);
+ do_setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+ do_setitimer(ITIMER_PROF, &itimer, NULL);
+
spin_lock_irq(¤t->sighand->siglock);
pending = ¤t->signal->shared_pending;
flush_sigqueue(pending);
pending->signal = new_pending.signal;
list_splice_init(&new_pending.list, &pending->list);
spin_unlock_irq(¤t->sighand->siglock);
+
+ /* real/virt/prof itimers */
+ itimer.it_value = ns_to_timeval(h->it_real_value);
+ itimer.it_interval = ns_to_timeval(h->it_real_incr);
+ ret = do_setitimer(ITIMER_REAL, &itimer, NULL);
+ if (ret < 0)
+ goto out;
+ itimer.it_value = ns_to_timeval(h->it_virt_value);
+ itimer.it_interval = ns_to_timeval(h->it_virt_incr);
+ ret = do_setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+ if (ret < 0)
+ goto out;
+ itimer.it_value = ns_to_timeval(h->it_prof_value);
+ itimer.it_interval = ns_to_timeval(h->it_prof_incr);
+ ret = do_setitimer(ITIMER_PROF, &itimer, NULL);
out:
ckpt_hdr_put(ctx, h);
return ret;
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 9dcb160..a0ec25f 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -472,6 +472,12 @@ struct ckpt_hdr_rlimit {
struct ckpt_hdr_signal {
struct ckpt_hdr h;
struct ckpt_hdr_rlimit rlim[CKPT_RLIM_NLIMITS];
+ __u64 it_real_value;
+ __u64 it_real_incr;
+ __u64 it_virt_value;
+ __u64 it_virt_incr;
+ __u64 it_prof_value;
+ __u64 it_prof_incr;
} __attribute__((aligned(8)));
struct ckpt_hdr_signal_task {
--
1.6.0.4
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list