epoll: add PRI_EVENTS for watching sysfs attributes
Sysfs attributes signal change through sysfs_notify, which wakes pollers
with POLLPRI rather than POLLIN. There was no way to ask for that: the
flag set stopped at IN/OUT/ERR, so a watcher on a file like
/sys/class/backlight/*/actual_brightness could never fire.
Add PRI_EVENTS and map it onto EPOLLPRI in the epoll backend. The generic
layer already passes watch flags through to the backend untouched, and the
IO_EVENTS masking only applies to the regular-file emulation path, which
epoll does not take for sysfs attributes.
Only the epoll backend implements this; the kqueue and select backends
ignore the flag.2 files changed +11 −2
- • include/dasynq/epoll.h
- • include/dasynq/flags.h
| 1 | diff --git a/include/dasynq/epoll.h b/include/dasynq/epoll.h |
| 2 | index 92eba6e..fe783cd 100644 |
| 3 | --- a/include/dasynq/epoll.h |
| 4 | +++ b/include/dasynq/epoll.h |
| 5 | @@ -153,6 +153,7 @@ template <class Base> class epoll_loop : public Base |
| 6 | int flags = 0; |
| 7 | (events[i].events & EPOLLIN) && (flags |= IN_EVENTS); |
| 8 | (events[i].events & EPOLLOUT) && (flags |= OUT_EVENTS); |
| 9 | + (events[i].events & EPOLLPRI) && (flags |= PRI_EVENTS); |
| 10 | // We mustn't introduce IN/OUT events for error conditions as we don't know which are being |
| 11 | // watched! Just set ERR_EVENTS. |
| 12 | (events[i].events & EPOLLHUP) && (flags |= ERR_EVENTS); |
| 13 | @@ -211,7 +212,7 @@ template <class Base> class epoll_loop : public Base |
| 14 | |
| 15 | // fd: file descriptor to watch |
| 16 | // userdata: data to associate with descriptor |
| 17 | - // flags: IN_EVENTS | OUT_EVENTS | ONE_SHOT |
| 18 | + // flags: IN_EVENTS | OUT_EVENTS | PRI_EVENTS | ONE_SHOT |
| 19 | // soft_fail: true if unsupported file descriptors should fail by returning false instead |
| 20 | // of throwing an exception |
| 21 | // returns: true on success; false if file descriptor type isn't supported and soft_fail == true |
| 22 | @@ -232,6 +233,9 @@ template <class Base> class epoll_loop : public Base |
| 23 | if ((flags & OUT_EVENTS) && enabled) { |
| 24 | epevent.events |= EPOLLOUT; |
| 25 | } |
| 26 | + if ((flags & PRI_EVENTS) && enabled) { |
| 27 | + epevent.events |= EPOLLPRI; |
| 28 | + } |
| 29 | |
| 30 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &epevent) == -1) { |
| 31 | if (soft_fail && errno == EPERM) { |
| 32 | @@ -284,7 +288,10 @@ template <class Base> class epoll_loop : public Base |
| 33 | if (flags & OUT_EVENTS) { |
| 34 | epevent.events |= EPOLLOUT; |
| 35 | } |
| 36 | - |
| 37 | + if (flags & PRI_EVENTS) { |
| 38 | + epevent.events |= EPOLLPRI; |
| 39 | + } |
| 40 | + |
| 41 | if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &epevent) == -1) { |
| 42 | // Shouldn't be able to fail |
| 43 | // throw std::system_error(errno, std::system_category()); |
| 44 | diff --git a/include/dasynq/flags.h b/include/dasynq/flags.h |
| 45 | index 5b4a38a..7af01a9 100644 |
| 46 | --- a/include/dasynq/flags.h |
| 47 | +++ b/include/dasynq/flags.h |
| 48 | @@ -10,6 +10,8 @@ constexpr unsigned int ERR_EVENTS = 4; |
| 49 | |
| 50 | constexpr unsigned int ONE_SHOT = 8; |
| 51 | |
| 52 | +constexpr unsigned int PRI_EVENTS = 16; |
| 53 | + |
| 54 | // Masks: |
| 55 | constexpr unsigned int IO_EVENTS = IN_EVENTS | OUT_EVENTS; |
| 56 |