X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=test%2Ftest.c;fp=test%2Ftest.c;h=b4f2f67f08f677684f91476feb340d1c1b7535dd;hb=98c615b91f0da85c9bd00bbff7a8fd1258400ab9;hp=0000000000000000000000000000000000000000;hpb=a5f7e5aaf5bb2168aca37066eb6b49d126689aa6;p=~madcoder%2Fpwqr.git diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..b4f2f67 --- /dev/null +++ b/test/test.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2012 Pierre Habouzit + * Copyright (C) 2012 Intersec SAS + * + * This file is part of the Linux Pthread Workqueue Regulator tests. + * + * The Linux Pthread Workqueue Regulator is free software: you can + * redistribute it and/or modify it under the terms of the GNU Lesser + * General Public License as published by the Free Software Foundation, + * either version 2.1 of the License, or (at your option) any later version. + * + * The Linux Pthread Workqueue Regulator is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The Linux Pthread Workqueue Regultaor. + * If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kernel/pwqr.h" + +/* pwqr wrapping {{{ */ + +static int pwqr_create(int flags) +{ + if (flags & ~PWQR_FL__SET) { + errno = -EINVAL; + return -1; + } + return open("/dev/"PWQR_DEVICE_NAME, O_RDWR | flags); +} + +static int pwqr_ctl(int fd, int op, int val, void *uaddr) +{ + struct pwqr_ioc_wait wait; + + switch (op) { + case PWQR_CTL_GET_CONC: + case PWQR_CTL_REGISTER: + case PWQR_CTL_UNREGISTER: + case PWQR_CTL_PARK: + return ioctl(fd, op); + case PWQR_CTL_SET_CONC: + case PWQR_CTL_WAKE: + case PWQR_CTL_WAKE_OC: + return ioctl(fd, op, val); + case PWQR_CTL_WAIT: + wait.pwqr_ticket = val; + wait.pwqr_uaddr = uaddr; + return ioctl(fd, op, &wait); + default: + errno = EINVAL; + return -1; + } +} + +/* }}} */ + +static int pwqr_fd_g = -1; +static int pi_g; + +static void *thr_main(void *unused) +{ + if (pwqr_ctl(pwqr_fd_g, PWQR_CTL_REGISTER, 0, NULL) < 0) + err(-1, "pwqr_ctl(PWQR_CTL_REGISTER)"); + + /* busy-loop */ + for (;;) + pthread_testcancel(); + return NULL; +} + +static uint64_t tv_diff(const struct timeval *t1, const struct timeval *t2) +{ + return (t1->tv_sec - t2->tv_sec) * 1000000ULL + t1->tv_usec - t2->tv_usec; +} + +int main(void) +{ + pthread_t tids[32]; + struct pollfd pfd; + struct timeval start, tv; + int rc; + + pwqr_fd_g = pwqr_create(PWQR_FL_NONBLOCK); + if (pwqr_fd_g < 0) + err(-1, "pwqr_create"); + + pi_g = pwqr_ctl(pwqr_fd_g, PWQR_CTL_GET_CONC, 0, NULL); + if (pi_g < 1) + err(-1, "pwqr_ctl(PWQR_CTL_GET_CONC)"); + + for (int i = 0; i < pi_g + 1; i++) { + pthread_create(&tids[i], NULL, thr_main, NULL); + } + + pfd.fd = pwqr_fd_g; + pfd.events = POLLIN; + gettimeofday(&start, NULL); + for (;;) { + pfd.revents = 0; + rc = poll(&pfd, 1, -1); + if (rc < 0) { + warn("poll"); + continue; + } + if (rc == 1) { + if (pfd.revents & POLLIN) { + if (read(pwqr_fd_g, &rc, sizeof(rc)) != sizeof(rc)) { + warn("read"); + } else { + gettimeofday(&tv, NULL); + warnx("[%06jd.%06jd] overcommit of %d", + tv_diff(&tv, &start) / 1000000, + tv_diff(&tv, &start) % 1000000, rc); + } + } + if (pfd.revents & POLLHUP) { + errx(-1, "poll returned POLLHUP"); + } + } + } + + for (int i = 0; i < pi_g + 1; i++) { + pthread_join(tids[i], NULL); + } + return 0; +}