Back to home page

OSCL-LXR

 
 

    


0001 /* Time inconsistency check test
0002  *      by: john stultz (johnstul@us.ibm.com)
0003  *      (C) Copyright IBM 2003, 2004, 2005, 2012
0004  *      (C) Copyright Linaro Limited 2015
0005  *      Licensed under the GPLv2
0006  *
0007  *  To build:
0008  *  $ gcc inconsistency-check.c -o inconsistency-check -lrt
0009  *
0010  *   This program is free software: you can redistribute it and/or modify
0011  *   it under the terms of the GNU General Public License as published by
0012  *   the Free Software Foundation, either version 2 of the License, or
0013  *   (at your option) any later version.
0014  *
0015  *   This program is distributed in the hope that it will be useful,
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  *   GNU General Public License for more details.
0019  */
0020 
0021 
0022 
0023 #include <stdio.h>
0024 #include <unistd.h>
0025 #include <stdlib.h>
0026 #include <time.h>
0027 #include <sys/time.h>
0028 #include <sys/timex.h>
0029 #include <string.h>
0030 #include <signal.h>
0031 #include "../kselftest.h"
0032 
0033 #define CALLS_PER_LOOP 64
0034 #define NSEC_PER_SEC 1000000000ULL
0035 
0036 #define CLOCK_REALTIME          0
0037 #define CLOCK_MONOTONIC         1
0038 #define CLOCK_PROCESS_CPUTIME_ID    2
0039 #define CLOCK_THREAD_CPUTIME_ID     3
0040 #define CLOCK_MONOTONIC_RAW     4
0041 #define CLOCK_REALTIME_COARSE       5
0042 #define CLOCK_MONOTONIC_COARSE      6
0043 #define CLOCK_BOOTTIME          7
0044 #define CLOCK_REALTIME_ALARM        8
0045 #define CLOCK_BOOTTIME_ALARM        9
0046 #define CLOCK_HWSPECIFIC        10
0047 #define CLOCK_TAI           11
0048 #define NR_CLOCKIDS         12
0049 
0050 char *clockstring(int clockid)
0051 {
0052     switch (clockid) {
0053     case CLOCK_REALTIME:
0054         return "CLOCK_REALTIME";
0055     case CLOCK_MONOTONIC:
0056         return "CLOCK_MONOTONIC";
0057     case CLOCK_PROCESS_CPUTIME_ID:
0058         return "CLOCK_PROCESS_CPUTIME_ID";
0059     case CLOCK_THREAD_CPUTIME_ID:
0060         return "CLOCK_THREAD_CPUTIME_ID";
0061     case CLOCK_MONOTONIC_RAW:
0062         return "CLOCK_MONOTONIC_RAW";
0063     case CLOCK_REALTIME_COARSE:
0064         return "CLOCK_REALTIME_COARSE";
0065     case CLOCK_MONOTONIC_COARSE:
0066         return "CLOCK_MONOTONIC_COARSE";
0067     case CLOCK_BOOTTIME:
0068         return "CLOCK_BOOTTIME";
0069     case CLOCK_REALTIME_ALARM:
0070         return "CLOCK_REALTIME_ALARM";
0071     case CLOCK_BOOTTIME_ALARM:
0072         return "CLOCK_BOOTTIME_ALARM";
0073     case CLOCK_TAI:
0074         return "CLOCK_TAI";
0075     }
0076     return "UNKNOWN_CLOCKID";
0077 }
0078 
0079 /* returns 1 if a <= b, 0 otherwise */
0080 static inline int in_order(struct timespec a, struct timespec b)
0081 {
0082     /* use unsigned to avoid false positives on 2038 rollover */
0083     if ((unsigned long)a.tv_sec < (unsigned long)b.tv_sec)
0084         return 1;
0085     if ((unsigned long)a.tv_sec > (unsigned long)b.tv_sec)
0086         return 0;
0087     if (a.tv_nsec > b.tv_nsec)
0088         return 0;
0089     return 1;
0090 }
0091 
0092 
0093 
0094 int consistency_test(int clock_type, unsigned long seconds)
0095 {
0096     struct timespec list[CALLS_PER_LOOP];
0097     int i, inconsistent;
0098     long now, then;
0099     time_t t;
0100     char *start_str;
0101 
0102     clock_gettime(clock_type, &list[0]);
0103     now = then = list[0].tv_sec;
0104 
0105     /* timestamp start of test */
0106     t = time(0);
0107     start_str = ctime(&t);
0108 
0109     while (seconds == -1 || now - then < seconds) {
0110         inconsistent = -1;
0111 
0112         /* Fill list */
0113         for (i = 0; i < CALLS_PER_LOOP; i++)
0114             clock_gettime(clock_type, &list[i]);
0115 
0116         /* Check for inconsistencies */
0117         for (i = 0; i < CALLS_PER_LOOP - 1; i++)
0118             if (!in_order(list[i], list[i+1]))
0119                 inconsistent = i;
0120 
0121         /* display inconsistency */
0122         if (inconsistent >= 0) {
0123             unsigned long long delta;
0124 
0125             ksft_print_msg("\%s\n", start_str);
0126             for (i = 0; i < CALLS_PER_LOOP; i++) {
0127                 if (i == inconsistent)
0128                     ksft_print_msg("--------------------\n");
0129                 ksft_print_msg("%lu:%lu\n", list[i].tv_sec,
0130                             list[i].tv_nsec);
0131                 if (i == inconsistent + 1)
0132                     ksft_print_msg("--------------------\n");
0133             }
0134             delta = list[inconsistent].tv_sec * NSEC_PER_SEC;
0135             delta += list[inconsistent].tv_nsec;
0136             delta -= list[inconsistent+1].tv_sec * NSEC_PER_SEC;
0137             delta -= list[inconsistent+1].tv_nsec;
0138             ksft_print_msg("Delta: %llu ns\n", delta);
0139             fflush(0);
0140             /* timestamp inconsistency*/
0141             t = time(0);
0142             ksft_print_msg("%s\n", ctime(&t));
0143             return -1;
0144         }
0145         now = list[0].tv_sec;
0146     }
0147     return 0;
0148 }
0149 
0150 
0151 int main(int argc, char *argv[])
0152 {
0153     int clockid, opt;
0154     int userclock = CLOCK_REALTIME;
0155     int maxclocks = NR_CLOCKIDS;
0156     int runtime = 10;
0157     struct timespec ts;
0158 
0159     /* Process arguments */
0160     while ((opt = getopt(argc, argv, "t:c:")) != -1) {
0161         switch (opt) {
0162         case 't':
0163             runtime = atoi(optarg);
0164             break;
0165         case 'c':
0166             userclock = atoi(optarg);
0167             maxclocks = userclock + 1;
0168             break;
0169         default:
0170             printf("Usage: %s [-t <secs>] [-c <clockid>]\n", argv[0]);
0171             printf("    -t: Number of seconds to run\n");
0172             printf("    -c: clockid to use (default, all clockids)\n");
0173             exit(-1);
0174         }
0175     }
0176 
0177     setbuf(stdout, NULL);
0178 
0179     ksft_print_header();
0180     ksft_set_plan(maxclocks - userclock);
0181 
0182     for (clockid = userclock; clockid < maxclocks; clockid++) {
0183 
0184         if (clockid == CLOCK_HWSPECIFIC || clock_gettime(clockid, &ts)) {
0185             ksft_test_result_skip("%-31s\n", clockstring(clockid));
0186             continue;
0187         }
0188 
0189         if (consistency_test(clockid, runtime)) {
0190             ksft_test_result_fail("%-31s\n", clockstring(clockid));
0191             ksft_exit_fail();
0192         } else {
0193             ksft_test_result_pass("%-31s\n", clockstring(clockid));
0194         }
0195     }
0196     ksft_exit_pass();
0197 }