|  | /* 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); | 
|  | } |