| /* Copyright (c) 2015 Google Inc. |
| * Barret Rhoden <brho@cs.berkeley.edu> |
| * See LICENSE for details. |
| * |
| * Implementation of glibc's eventfd interface, hooking in to #eventfd */ |
| |
| #include <sys/eventfd.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sys/plan9_helpers.h> |
| |
| /* Gets a new EFD instance, returning the FD on success. */ |
| int eventfd(int initval, int flags) |
| { |
| const char *pathname = "#eventfd/efd"; |
| int oflags = 0; |
| int efd; |
| |
| /* we choose semaphore mode by passing 'sem' as the device spec */ |
| if (flags & EFD_SEMAPHORE) |
| pathname = "#eventfd.sem/efd"; |
| if (flags & EFD_CLOEXEC) |
| oflags |= O_CLOEXEC; |
| if (flags & EFD_NONBLOCK) |
| oflags |= O_NONBLOCK; |
| efd = open(pathname, O_READ | O_WRITE | oflags); |
| if (efd < 0) |
| return efd; |
| /* default initval for an #eventfd is 0. */ |
| if (initval) { |
| if (eventfd_write(efd, initval)) { |
| close(efd); |
| return -1; |
| } |
| } |
| return efd; |
| } |
| |
| /* Reads into *value, in host-endian format, from the efd. Returns 0 on |
| * success. */ |
| int eventfd_read(int efd, eventfd_t *value) |
| { |
| int ret; |
| char num64[32]; |
| |
| ret = read(efd, num64, sizeof(num64)); |
| if (ret <= 0) |
| return -1; |
| *value = strtoul(num64, 0, 0); |
| return 0; |
| } |
| |
| /* Writes value, in host-endian format, into the efd. Returns 0 on success. */ |
| int eventfd_write(int efd, eventfd_t value) |
| { |
| return write_hex_to_fd(efd, value); |
| } |