Add stupid tests.
[~madcoder/pwqr.git] / test / test.c
1 /*
2  * Copyright (C) 2012   Pierre Habouzit <pierre.habouzit@intersec.com>
3  * Copyright (C) 2012   Intersec SAS
4  *
5  * This file is part of the Linux Pthread Workqueue Regulator tests.
6  *
7  * The Linux Pthread Workqueue Regulator is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU Lesser
9  * General Public License as published by the Free Software Foundation,
10  * either version 2.1 of the License, or (at your option) any later version.
11  *
12  * The Linux Pthread Workqueue Regulator is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with The Linux Pthread Workqueue Regultaor.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <assert.h>
23 #include <err.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <pthread.h>
27 #include <sched.h>
28 #include <stddef.h>
29 #include <stdint.h>
30 #include <sys/ioctl.h>
31 #include <sys/poll.h>
32 #include <sys/time.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35
36 #include "../kernel/pwqr.h"
37
38 /* pwqr wrapping {{{ */
39
40 static int pwqr_create(int flags)
41 {
42     if (flags & ~PWQR_FL__SET) {
43         errno = -EINVAL;
44         return -1;
45     }
46     return open("/dev/"PWQR_DEVICE_NAME, O_RDWR | flags);
47 }
48
49 static int pwqr_ctl(int fd, int op, int val, void *uaddr)
50 {
51     struct pwqr_ioc_wait wait;
52
53     switch (op) {
54       case PWQR_CTL_GET_CONC:
55       case PWQR_CTL_REGISTER:
56       case PWQR_CTL_UNREGISTER:
57       case PWQR_CTL_PARK:
58         return ioctl(fd, op);
59       case PWQR_CTL_SET_CONC:
60       case PWQR_CTL_WAKE:
61       case PWQR_CTL_WAKE_OC:
62         return ioctl(fd, op, val);
63       case PWQR_CTL_WAIT:
64         wait.pwqr_ticket = val;
65         wait.pwqr_uaddr  = uaddr;
66         return ioctl(fd, op, &wait);
67       default:
68         errno = EINVAL;
69         return -1;
70     }
71 }
72
73 /* }}} */
74
75 static int pwqr_fd_g = -1;
76 static int pi_g;
77
78 static void *thr_main(void *unused)
79 {
80     if (pwqr_ctl(pwqr_fd_g, PWQR_CTL_REGISTER, 0, NULL) < 0)
81         err(-1, "pwqr_ctl(PWQR_CTL_REGISTER)");
82
83     /* busy-loop */
84     for (;;)
85         pthread_testcancel();
86     return NULL;
87 }
88
89 static uint64_t tv_diff(const struct timeval *t1, const struct timeval *t2)
90 {
91     return (t1->tv_sec - t2->tv_sec) * 1000000ULL + t1->tv_usec - t2->tv_usec;
92 }
93
94 int main(void)
95 {
96     pthread_t tids[32];
97     struct pollfd pfd;
98     struct timeval start, tv;
99     int rc;
100
101     pwqr_fd_g = pwqr_create(PWQR_FL_NONBLOCK);
102     if (pwqr_fd_g < 0)
103         err(-1, "pwqr_create");
104
105     pi_g = pwqr_ctl(pwqr_fd_g, PWQR_CTL_GET_CONC, 0, NULL);
106     if (pi_g < 1)
107         err(-1, "pwqr_ctl(PWQR_CTL_GET_CONC)");
108
109     for (int i = 0; i < pi_g + 1; i++) {
110         pthread_create(&tids[i], NULL, thr_main, NULL);
111     }
112
113     pfd.fd     = pwqr_fd_g;
114     pfd.events = POLLIN;
115     gettimeofday(&start, NULL);
116     for (;;) {
117         pfd.revents = 0;
118         rc = poll(&pfd, 1, -1);
119         if (rc < 0) {
120             warn("poll");
121             continue;
122         }
123         if (rc == 1) {
124             if (pfd.revents & POLLIN) {
125                 if (read(pwqr_fd_g, &rc, sizeof(rc)) != sizeof(rc)) {
126                     warn("read");
127                 } else {
128                     gettimeofday(&tv, NULL);
129                     warnx("[%06jd.%06jd] overcommit of %d",
130                           tv_diff(&tv, &start) / 1000000,
131                           tv_diff(&tv, &start) % 1000000, rc);
132                 }
133             }
134             if (pfd.revents & POLLHUP) {
135                 errx(-1, "poll returned POLLHUP");
136             }
137         }
138     }
139
140     for (int i = 0; i < pi_g + 1; i++) {
141         pthread_join(tids[i], NULL);
142     }
143     return 0;
144 }