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
1diff --git a/include/dasynq/epoll.h b/include/dasynq/epoll.h
2index 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());
44diff --git a/include/dasynq/flags.h b/include/dasynq/flags.h
45index 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