File: timerfd.c

package info (click to toggle)
valgrind 1%3A3.24.0-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 176,332 kB
  • sloc: ansic: 795,029; exp: 26,134; xml: 23,472; asm: 14,393; cpp: 9,397; makefile: 7,464; sh: 6,122; perl: 5,446; python: 1,498; javascript: 981; awk: 166; csh: 1
file content (150 lines) | stat: -rw-r--r-- 4,160 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* Copied from the Linux manpage
 * with the printed times rounded to
 * seconds for reproducibility.
 * And some errors added.
 */

#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <assert.h>
#include "../../memcheck.h"

static void
print_elapsed_time(void)
{
    int                     secs, nsecs;
    static int              first_call = 1;
    struct timespec         curr;
    static struct timespec  start;
    int                  round_secs;

    if (first_call) {
        first_call = 0;
        if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
            err(EXIT_FAILURE, "clock_gettime");
    }

    if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
        err(EXIT_FAILURE, "clock_gettime");

    secs = curr.tv_sec - start.tv_sec;
    nsecs = curr.tv_nsec - start.tv_nsec;
    if (nsecs < 0) {
        secs--;
        nsecs += 1000000000;
    }
    round_secs = round((secs*1e9 + nsecs)/1e9);
    printf("%d: ", round_secs);
}

int
main(int argc, char *argv[])
{
    int                fd;
    ssize_t            s;
    uint64_t           exp, tot_exp, max_exp;
    struct timespec    now;
    struct itimerspec  new_value;

    if (argc != 2 && argc != 4) {
        fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
                argv[0]);
        exit(EXIT_FAILURE);
    }

    if (clock_gettime(CLOCK_REALTIME, &now) == -1)
        err(EXIT_FAILURE, "clock_gettime");

    /* Create a CLOCK_REALTIME absolute timer with initial
       expiration and interval as specified in command line. */

    new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
    new_value.it_value.tv_nsec = now.tv_nsec;
    if (argc == 2) {
        new_value.it_interval.tv_sec = 0;
        max_exp = 1;
    } else {
        new_value.it_interval.tv_sec = atoi(argv[2]);
        max_exp = atoi(argv[3]);
    }
    new_value.it_interval.tv_nsec = 0;

    fd = timerfd_create(CLOCK_REALTIME, 0);
    if (fd == -1)
        err(EXIT_FAILURE, "timerfd_create");

    if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
        err(EXIT_FAILURE, "timerfd_settime");

    print_elapsed_time();
    printf("timer started\n");

    for (tot_exp = 0; tot_exp < max_exp;) {
        s = read(fd, &exp, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
            err(EXIT_FAILURE, "read");

        tot_exp += exp;
        print_elapsed_time();
        printf("read: %" PRIu64 "; total=%" PRIu64 "\n", exp, tot_exp);
    }

    close(fd);

    {
        int a = CLOCK_REALTIME;
        int b = TFD_CLOEXEC;
        int c = TFD_TIMER_ABSTIME;
        VALGRIND_MAKE_MEM_UNDEFINED(&a, sizeof(a));
        VALGRIND_MAKE_MEM_UNDEFINED(&b, sizeof(b));
        VALGRIND_MAKE_MEM_UNDEFINED(&c, sizeof(c));
        struct itimerspec * get_ts = malloc(sizeof(*get_ts) - 2);
        struct itimerspec * set_ts = malloc(sizeof(*set_ts) - 2);
        struct itimerspec ts;
        int retval;

        errno = 0;
        /* uninit clockid and flag but should work */
        int fd2 = timerfd_create(a, b);
        assert(fd2 != -1);
        assert(errno == 0); 
        /* bad flag should fail */
        timerfd_create(CLOCK_REALTIME, 1000000);
        /* bad clockid should fail */
        timerfd_create(1000000, TFD_CLOEXEC);

        /* memory too small for requested get */
        timerfd_gettime(fd2, get_ts);
        /* should succeed */
        timerfd_gettime(fd2, &ts);
        ts.it_interval.tv_nsec += 100000;

        /* uninit flag */
        timerfd_settime(fd2, c, &ts, NULL);
        errno = 0;
        ts.it_interval.tv_nsec += 100000;
        /* memory too small for requested old value */
        retval = timerfd_settime(fd2, TFD_TIMER_ABSTIME, &ts, set_ts);
        assert(retval == 0);
        assert(errno == 0);

        VALGRIND_MAKE_MEM_UNDEFINED(&fd2, sizeof(fd2));
        timerfd_gettime(fd2, &ts);
        ts.it_interval.tv_nsec += 100000;
        timerfd_settime(fd2, TFD_TIMER_ABSTIME, &ts, NULL);


        free(get_ts); 
        free(set_ts); 
    }

    exit(EXIT_SUCCESS);
}