1 /******************************************************************************* 2 3 Linux custom file descriptor event. 4 5 eventfd man page follows: 6 7 Creates an "eventfd object" that can be used as an event wait/notify 8 mechanism by userspace applications, and by the kernel to notify userspace 9 applications of events. The object contains an unsigned 64-bit integer 10 (ulong) counter that is maintained by the kernel. 11 12 The following operations can be performed on the file descriptor: 13 14 read(2) 15 If the eventfd counter has a nonzero value, then a read(2) returns 8 16 bytes containing that value, and the counter's value is reset to zero. 17 (The returned value is in host byte order, i.e., the native byte order 18 for integers on the host machine.) 19 If the counter is zero at the time of the read(2), then the call either 20 blocks until the counter becomes nonzero, or fails with the error EAGAIN 21 if the file descriptor has been made non-blocking (via the use of the 22 fcntl(2) F_SETFL operation to set the O_NONBLOCK flag). 23 24 A read(2) will fail with the error EINVAL if the size of the supplied 25 buffer is less than 8 bytes. 26 27 write(2) 28 A write(2) call adds the 8-byte integer value supplied in its buffer to 29 the counter. The maximum value that may be stored in the counter is the 30 largest unsigned 64-bit value minus 1 (i.e., 0xfffffffffffffffe). If 31 the addition would cause the counter's value to exceed the maximum, 32 then the write(2) either blocks until a read(2) is performed on the file 33 descriptor, or fails with the error EAGAIN if the file descriptor has 34 been made non-blocking. 35 A write(2) will fail with the error EINVAL if the size of the supplied 36 buffer is less than 8 bytes, or if an attempt is made to write the value 37 0xffffffffffffffff. 38 39 poll(2), select(2) (and similar) 40 The returned file descriptor supports poll(2) (and analogously epoll(7)) 41 and select(2), as follows: 42 43 The file descriptor is readable (the select(2) readfds argument; the 44 poll(2) POLLIN flag) if the counter has a value greater than 0. 45 46 The file descriptor is writable (the select(2) writefds argument; the 47 poll(2) POLLOUT flag) if it is possible to write a value of at least 48 "1" without blocking. 49 50 The file descriptor indicates an exceptional condition (the select(2) 51 exceptfds argument; the poll(2) POLLERR flag) if an overflow of the 52 counter value was detected. As noted above, write(2) can never overflow 53 the counter. However an overflow can occur if 2^64 eventfd "signal 54 posts" were performed by the KAIO subsystem (theoretically possible, 55 but practically unlikely). If an overflow has occurred, then read(2) 56 will return that maximum uint64_t value (i.e., 0xffffffffffffffff). The 57 eventfd file descriptor also supports the other file-descriptor 58 multiplexing APIs: pselect(2), ppoll(2), and epoll(7). 59 60 close(2) 61 When the file descriptor is no longer required it should be closed. 62 When all file descriptors associated with the same eventfd object have 63 been closed, the resources for object are freed by the kernel. 64 65 A copy of the file descriptor created by eventfd() is inherited by the child 66 produced by fork(2). The duplicate file descriptor is associated with the 67 same eventfd object. File descriptors created by eventfd() are preserved 68 across execve(2). 69 70 Copyright: 71 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 72 All rights reserved. 73 74 License: 75 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 76 Alternatively, this file may be distributed under the terms of the Tango 77 3-Clause BSD License (see LICENSE_BSD.txt for details). 78 79 *******************************************************************************/ 80 81 module ocean.sys.EventFD; 82 83 import ocean.io.model.IConduit; 84 85 import core.sys.posix.sys.types: ssize_t; 86 import core.sys.posix.unistd: read, write, close; 87 88 /******************************************************************************* 89 90 Definition of external functions required to manage custom events. 91 92 Params: 93 initval = initial counter value 94 flags = Starting with Linux 2.6.27: 0 or a bitwise OR combination of 95 - EFD_NONBLOCK: Set the O_NONBLOCK file status flag on the 96 new open file description. 97 - EFD_CLOEXEC: Set the close-on-exec (FD_CLOEXEC) flag on 98 the new file descriptor. (See the description of the 99 O_CLOEXEC flag in open(2) for reasons why this may be 100 useful.) 101 102 Up to Linux version 2.6.26: Must be 0. 103 104 Returns: 105 new file descriptor that can be used to refer to the eventfd object 106 107 *******************************************************************************/ 108 109 private extern ( C ) 110 { 111 int eventfd ( uint initval, int flags ); 112 static immutable EFD_CLOEXEC = 0x80000; 113 } 114 115 116 117 /******************************************************************************* 118 119 Event fd class 120 121 *******************************************************************************/ 122 123 public class EventFD : ISelectable 124 { 125 import ocean.sys.CloseOnExec; 126 127 /*************************************************************************** 128 129 Integer file descriptor provided by the operating system and used to 130 manage the custom event. 131 132 ***************************************************************************/ 133 134 private int fd; 135 136 137 /*************************************************************************** 138 139 Constructor. Creates a custom event file descriptor. 140 141 ***************************************************************************/ 142 143 public this ( ) 144 { 145 this.fd = .eventfd(0, setCloExec(0, EFD_CLOEXEC)); 146 } 147 148 149 /*************************************************************************** 150 151 Destructor. Destroys the event file descriptor. 152 153 ***************************************************************************/ 154 155 ~this ( ) 156 { 157 .close(this.fd); 158 } 159 160 161 /*************************************************************************** 162 163 Required by ISelectable interface. 164 165 Returns: 166 file descriptor used to manage custom event 167 168 ***************************************************************************/ 169 170 public Handle fileHandle ( ) 171 { 172 return cast(Handle)this.fd; 173 } 174 175 176 /*************************************************************************** 177 178 Triggers the custom event one or more times. 179 180 Params: 181 n = number of times to trigger the event (defaults to 1) 182 183 ***************************************************************************/ 184 185 public void trigger ( ulong n = 1 ) 186 { 187 this.write(n); 188 } 189 190 191 /*************************************************************************** 192 193 Should be called when the custom event has fired. 194 195 Returns: 196 the number of times the event has been triggered since the last call 197 to handle(). 198 199 ***************************************************************************/ 200 201 public ulong handle ( ) 202 { 203 ulong n; 204 this.read(n); 205 206 return n; 207 } 208 209 210 /*************************************************************************** 211 212 Writes to the custom event file descriptor. 213 214 A write() call adds the ulong value supplied in its buffer to the 215 counter. The maximum value that may be stored in the counter is 216 ulong.max - 1. If the addition would cause the counter's value to 217 exceed the maximum, write() either blocks until a read() is 218 performed or fails with the error EAGAIN if the file descriptor has 219 been made non-blocking. 220 A write() will fail with the error EINVAL if an attempt is made to 221 write the value ulong.max. 222 223 Params: 224 n = value to write 225 226 Returns: 227 ulong.sizeof on success or -1 on error. For -1 errno is set 228 appropriately. 229 230 ***************************************************************************/ 231 232 private ssize_t write ( ulong n ) 233 { 234 return .write(this.fd, &n, n.sizeof); 235 } 236 237 238 /*************************************************************************** 239 240 Reads from the custom event file descriptor. 241 242 If the eventfd counter has a nonzero value, then a read() returns 243 that value, and the counter's value is reset to zero. 244 If the counter is zero at the time of the read(), then the call 245 either blocks until the counter becomes nonzero, or fails with the 246 error EAGAIN if the file descriptor has been made non-blocking. 247 248 Params: 249 n = value output 250 251 Returns: 252 ulong.sizeof on success, 0 on end-of-file condition or -1 on 253 error. For 0 and -1 errno is set appropriately. 254 255 ***************************************************************************/ 256 257 private ssize_t read ( out ulong n ) 258 { 259 return .read(this.fd, &n, n.sizeof); 260 } 261 }