Add stupid tests.
[~madcoder/pwqr.git] / test / test.c
diff --git a/test/test.c b/test/test.c
new file mode 100644 (file)
index 0000000..b4f2f67
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012   Pierre Habouzit <pierre.habouzit@intersec.com>
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#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;
+}