akaros/tests/eventfd.c
<<
>>
Prefs
   1/* Copyright (c) 2015 Google Inc
   2 * Barret Rhoden <brho@cs.berkeley.edu>
   3 * See LICENSE for details.
   4 *
   5 * #eventfd test, using the glibc interface mostly. */
   6
   7#include <stdlib.h>
   8#include <stdio.h>
   9#include <parlib/parlib.h>
  10#include <unistd.h>
  11#include <pthread.h>
  12
  13#include <sys/types.h>
  14#include <sys/stat.h>
  15#include <fcntl.h>
  16#include <sys/eventfd.h>
  17#include <sys/epoll.h>
  18
  19
  20#define handle_error(msg) \
  21        do { perror(msg); exit(-1); } while (0)
  22
  23static void epoll_on_efd(int efd)
  24{
  25        #define EP_SET_SZ 10    /* this is actually the ID of the largest FD */
  26        int epfd = epoll_create(EP_SET_SZ);
  27        struct epoll_event ep_ev;
  28        struct epoll_event results[EP_SET_SZ];
  29
  30        if (epfd < 0)
  31                handle_error("epoll_create");
  32        ep_ev.events = EPOLLIN | EPOLLET;
  33        ep_ev.data.fd = efd;
  34        if (epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &ep_ev))
  35                handle_error("epoll_ctl_add eventfd");
  36        if (epoll_wait(epfd, results, EP_SET_SZ, -1) != 1)
  37                handle_error("epoll_wait");
  38        close(epfd);
  39}
  40
  41static pthread_attr_t pth_attrs;
  42static bool upped;
  43
  44static void *upper_thread(void *arg)
  45{
  46        int efd = (int)(long)arg;
  47        uthread_sleep(1);
  48        if (eventfd_write(efd, 1))
  49                handle_error("upper write");
  50        upped = TRUE;
  51        return 0;
  52}
  53
  54int main(int argc, char **argv)
  55{
  56        int ret;
  57        eventfd_t efd_val = 0;
  58        int efd;
  59        pthread_t child;
  60
  61        parlib_wants_to_be_mcp = FALSE; /* Make us an SCP with a 2LS */
  62        pthread_attr_init(&pth_attrs);
  63        if (pthread_attr_setdetachstate(&pth_attrs, PTHREAD_CREATE_DETACHED))
  64                handle_error("pth attrs");
  65
  66        /* Semaphore counter, nonblocking */
  67        efd = eventfd(2, EFD_SEMAPHORE | EFD_NONBLOCK);
  68        if (efd < 0)
  69                handle_error("open sem");
  70        if (eventfd_read(efd, &efd_val))
  71                handle_error("first read");
  72        assert(efd_val == 1);
  73        if (eventfd_read(efd, &efd_val))
  74                handle_error("second read");
  75        assert(efd_val == 1);   /* always get 1 back from the SEM */
  76        ret = eventfd_read(efd, &efd_val);
  77        if ((ret != -1) && (errno != EAGAIN))
  78                handle_error("third read should be EAGAIN");
  79
  80        if (pthread_create(&child, &pth_attrs, &upper_thread, (void*)(long)efd))
  81                handle_error("pth_create failed");
  82        epoll_on_efd(efd);
  83        if (eventfd_read(efd, &efd_val))
  84                handle_error("final read");
  85        assert(efd_val == 1);
  86        close(efd);
  87
  88        /* Regular counter */
  89        efd = eventfd(2, 0);
  90        if (efd < 0)
  91                handle_error("open nonsem");
  92        if (eventfd_read(efd, &efd_val))
  93                handle_error("first read nonsem");
  94        assert(efd_val == 2);
  95
  96        /* Will try to block in the kernel.  Using 'upped' to catch any quick
  97         * returns.  It's not full-proof, but it can catch an O_NONBLOCK */
  98        if (pthread_create(&child, &pth_attrs, &upper_thread, (void*)(long)efd))
  99                handle_error("pth_create failed");
 100        upped = FALSE;
 101        if (eventfd_read(efd, &efd_val))
 102                handle_error("blocking read nonsem");
 103        cmb();
 104        assert(upped && efd_val == 1);
 105
 106        /* Should still be 0.  Add 1 and then extract to see if it was. */
 107        if (eventfd_write(efd, 1))
 108                handle_error("write nonsem +1");
 109        if (eventfd_read(efd, &efd_val))
 110                handle_error("final read nonsem");
 111        /* 1 means it was 0 before we added 1.  it's 0 again, since we read. */
 112        assert(efd_val == 1);
 113        /* Test the max_val + 1 write */
 114        ret = eventfd_write(efd, -1);
 115        if ((ret != -1) && (errno != EINVAL))
 116                handle_error("write nonsem should have failed");
 117        if (eventfd_write(efd, 0xfffffffffffffffe))
 118                handle_error("largest legal write");
 119        close(efd);
 120
 121        return 0;
 122}
 123