[CRIU] [PATCH] zdtm: check one-shot posix timers
Andrew Vagin
avagin at parallels.com
Fri May 24 04:04:47 EDT 2013
On Tue, May 14, 2013 at 06:25:15PM +0400, Vladimir Davydov wrote:
> On 5/14/13 6:19 PM, Andrew Vagin wrote:
> >On Tue, May 14, 2013 at 05:41:22PM +0400, Vladimir Davydov wrote:
> >>
> >>With the patch zdtm will check not only periodic timers, but also
> >>one-shot ones.
> >
> >How?
>
> Set one-shot timer to expire in a very long interval (INT_MAX in the
> test), and check its remaining value after checkpoint/restore. The
> following relationship must hold:
>
> initial_value - remaining_value = time_passed
I whould lite to have this description in the commit message.
Acked-by: Andrew Vagin <avagin at parallels.com>
>
> >
> >>
> >>Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
> >>---
> >> test/zdtm/live/static/posix_timers.c | 108 ++++++++++++++++++++++++++++------
> >> 1 files changed, 90 insertions(+), 18 deletions(-)
> >>
> >
> >>diff --git a/test/zdtm/live/static/posix_timers.c b/test/zdtm/live/static/posix_timers.c
> >>index 587a6be..ae9a882 100644
> >>--- a/test/zdtm/live/static/posix_timers.c
> >>+++ b/test/zdtm/live/static/posix_timers.c
> >>@@ -3,6 +3,8 @@
> >> #include <signal.h>
> >> #include <time.h>
> >> #include <sys/time.h>
> >>+#include <limits.h>
> >>+#include <string.h>
> >>
> >> #include "zdtmtst.h"
> >>
> >>@@ -17,14 +19,24 @@ sigset_t mask;
> >>
> >> #define MAX_TIMER_DISPLACEMENT 10
> >>
> >>-static void realtime_handler(int sig, siginfo_t *si, void *uc);
> >>-static void monotonic_handler(int sig, siginfo_t *si, void *uc);
> >>+static void realtime_periodic_handler(int sig, siginfo_t *si, void *uc);
> >>+static void monotonic_periodic_handler(int sig, siginfo_t *si, void *uc);
> >>+static void realtime_oneshot_handler(int sig, siginfo_t *si, void *uc);
> >>+static void monotonic_oneshot_handler(int sig, siginfo_t *si, void *uc);
> >>+
> >>+enum {
> >>+ REALTIME_PERIODIC_INFO,
> >>+ MONOTONIC_PERIODIC_INFO,
> >>+ REALTIME_ONESHOT_INFO,
> >>+ MONOTONIC_ONESHOT_INFO,
> >>+};
> >>
> >> static struct posix_timers_info {
> >> char clock;
> >> char *name;
> >> void (*handler)(int sig, siginfo_t *si, void *uc);
> >> int sig;
> >>+ int oneshot;
> >> int ms_int;
> >> struct sigaction sa;
> >> int handler_status;
> >>@@ -33,17 +45,24 @@ static struct posix_timers_info {
> >> int overrun;
> >> struct timespec start, end;
> >> } posix_timers[] = {
> >>- [CLOCK_REALTIME] = {CLOCK_REALTIME, "REALTIME", realtime_handler, SIGALRM, 1},
> >>- [CLOCK_MONOTONIC] = {CLOCK_MONOTONIC, "MONOTONIC", monotonic_handler, SIGINT, 3},
> >>+ [REALTIME_PERIODIC_INFO] = {CLOCK_REALTIME, "REALTIME (periodic)",
> >>+ realtime_periodic_handler, SIGALRM, 0, 1},
> >>+ [MONOTONIC_PERIODIC_INFO] = {CLOCK_MONOTONIC, "MONOTONIC (periodic)",
> >>+ monotonic_periodic_handler, SIGINT, 0, 3},
> >>+ [REALTIME_ONESHOT_INFO] = {CLOCK_REALTIME, "REALTIME (oneshot)",
> >>+ realtime_oneshot_handler, SIGUSR1, 1, INT_MAX},
> >>+ [MONOTONIC_ONESHOT_INFO] = {CLOCK_MONOTONIC, "MONOTONIC (oneshot)",
> >>+ monotonic_oneshot_handler, SIGUSR2, 1, INT_MAX},
> >> { }
> >> };
> >>
> >>-static int check_handler_status(struct posix_timers_info *info, int ms_passed)
> >>+static int check_handler_status(struct posix_timers_info *info,
> >>+ struct itimerspec *its, int ms_passed)
> >> {
> >> int displacement;
> >> int timer_ms;
> >>
> >>- if (!info->handler_cnt) {
> >>+ if (!info->handler_cnt && !info->oneshot) {
> >> fail("%s: Signal handler wasn't called\n", info->name);
> >> return -EINVAL;
> >> }
> >>@@ -58,7 +77,41 @@ static int check_handler_status(struct posix_timers_info *info, int ms_passed)
> >> return -1;
> >> }
> >>
> >>- timer_ms = (info->overrun + info->handler_cnt) * info->ms_int;
> >>+ if (!info->oneshot && !its->it_value.tv_sec && !its->it_value.tv_nsec) {
> >>+ fail("%s: timer became unset\n", info->name);
> >>+ return -EFAULT;
> >>+ }
> >>+
> >>+ if (info->oneshot && (its->it_interval.tv_sec || its->it_interval.tv_nsec)) {
> >>+ fail("%s: timer became periodic\n", info->name);
> >>+ return -EFAULT;
> >>+ }
> >>+
> >>+ if (!info->oneshot && !its->it_interval.tv_sec && !its->it_interval.tv_nsec) {
> >>+ fail("%s: timer became oneshot\n", info->name);
> >>+ return -EFAULT;
> >>+ }
> >>+
> >>+ if (info->oneshot) {
> >>+ int val = its->it_value.tv_sec * 1000 + its->it_value.tv_nsec / 1000 / 1000;
> >>+ if (info->handler_cnt) {
> >>+ if (val != 0) {
> >>+ fail("%s: timer continues ticking after expiration\n", info->name);
> >>+ return -EFAULT;
> >>+ }
> >>+ if (info->handler_cnt > 1) {
> >>+ fail("%s: timer expired %d times\n", info->name, info->handler_cnt);
> >>+ return -EFAULT;
> >>+ }
> >>+ if (info->ms_int > ms_passed) {
> >>+ fail("%s: timer expired too early\n", info->name);
> >>+ return -EFAULT;
> >>+ }
> >>+ return 0;
> >>+ }
> >>+ timer_ms = info->ms_int - val;
> >>+ } else
> >>+ timer_ms = (info->overrun + info->handler_cnt) * info->ms_int;
> >> displacement = abs(ms_passed - timer_ms) * 100 / ms_passed;
> >>
> >> if (displacement > MAX_TIMER_DISPLACEMENT) {
> >>@@ -76,6 +129,7 @@ static int check_timers(void)
> >> struct posix_timers_info *info = posix_timers;
> >> int ms_passed;
> >> int status = 0;
> >>+ struct itimerspec val, oldval;
> >>
> >> if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) {
> >> fail("Failed to unlock signal\n");
> >>@@ -83,8 +137,9 @@ static int check_timers(void)
> >> }
> >>
> >> while (info->handler) {
> >>- if (timer_delete(info->timerid) == -1) {
> >>- fail("%s: Failed to delete timer\n", info->name);
> >>+ memset(&val, 0, sizeof(val));
> >>+ if (timer_settime(info->timerid, 0, &val, &oldval) == -1) {
> >>+ fail("%s: failed to reset timer\n", info->name);
> >> return -errno;
> >> }
> >>
> >>@@ -96,7 +151,7 @@ static int check_timers(void)
> >> ms_passed = (info->end.tv_sec - info->start.tv_sec) * 1000 +
> >> (info->end.tv_nsec - info->start.tv_nsec) / (1000 * 1000);
> >>
> >>- if (check_handler_status(info, ms_passed))
> >>+ if (check_handler_status(info, &oldval, ms_passed))
> >> status--;
> >> info++;
> >> }
> >>@@ -124,14 +179,28 @@ static void generic_handler(struct posix_timers_info *info,
> >> info->handler_cnt++;
> >> }
> >>
> >>-static void monotonic_handler(int sig, siginfo_t *si, void *uc)
> >>+static void monotonic_periodic_handler(int sig, siginfo_t *si, void *uc)
> >>+{
> >>+ generic_handler(si->si_value.sival_ptr,
> >>+ &posix_timers[MONOTONIC_PERIODIC_INFO], sig);
> >>+}
> >>+
> >>+static void monotonic_oneshot_handler(int sig, siginfo_t *si, void *uc)
> >>+{
> >>+ generic_handler(si->si_value.sival_ptr,
> >>+ &posix_timers[MONOTONIC_ONESHOT_INFO], sig);
> >>+}
> >>+
> >>+static void realtime_periodic_handler(int sig, siginfo_t *si, void *uc)
> >> {
> >>- generic_handler(si->si_value.sival_ptr, &posix_timers[CLOCK_MONOTONIC], sig);
> >>+ generic_handler(si->si_value.sival_ptr,
> >>+ &posix_timers[REALTIME_PERIODIC_INFO], sig);
> >> }
> >>
> >>-static void realtime_handler(int sig, siginfo_t *si, void *uc)
> >>+static void realtime_oneshot_handler(int sig, siginfo_t *si, void *uc)
> >> {
> >>- generic_handler(si->si_value.sival_ptr, &posix_timers[CLOCK_REALTIME], sig);
> >>+ generic_handler(si->si_value.sival_ptr,
> >>+ &posix_timers[REALTIME_ONESHOT_INFO], sig);
> >> }
> >>
> >> static int setup_timers(void)
> >>@@ -171,10 +240,13 @@ static int setup_timers(void)
> >> return -errno;
> >> }
> >>
> >>- its.it_value.tv_sec = 0;
> >>- its.it_value.tv_nsec = info->ms_int * 1000 * 1000;
> >>- its.it_interval.tv_sec = its.it_value.tv_sec;
> >>- its.it_interval.tv_nsec = its.it_value.tv_nsec;
> >>+ its.it_value.tv_sec = info->ms_int / 1000;
> >>+ its.it_value.tv_nsec = info->ms_int % 1000 * 1000 * 1000;
> >>+ if (!info->oneshot) {
> >>+ its.it_interval.tv_sec = its.it_value.tv_sec;
> >>+ its.it_interval.tv_nsec = its.it_value.tv_nsec;
> >>+ } else
> >>+ its.it_interval.tv_sec = its.it_interval.tv_nsec = 0;
> >>
> >> if (clock_gettime(info->clock, &info->start) == -1) {
> >> err("Can't get %s start time\n", info->name);
> >
> >>_______________________________________________
> >>CRIU mailing list
> >>CRIU at openvz.org
> >>https://lists.openvz.org/mailman/listinfo/criu
> >
>
More information about the CRIU
mailing list