5

I started to get in C programming with Linux and embedded systems (router hardware and openwrt). I have got interupts on GPIOs enabled, using poll works ... nearly.

I can use poll() and if i press the button to trigger the interrupt, poll() returns with a value > 0. So far so good. Now i try to use poll() on several GPIOs simultaniosly and therefor want to analyze the revents of every potential interrupt source. Allthough the interrupt seems to work, i get POLLPRI & POLLERR back and i do not understand why. Reducing the pollfd structure to 1 entry does not change anything.

char value;

int fd_btn1 = open("/sys/class/gpio/gpio14/value", O_RDONLY);
int fd_left = open("/sys/class/gpio/gpio12/value", O_RDONLY);
int fd_right = open("/sys/class/gpio/gpio13/value", O_RDONLY);

struct pollfd fds[3];
fds[0].fd = fd_btn1;
fds[1].fd = fd_left;
fds[2].fd = fd_right;
fds[0].events = POLLPRI;
fds[1].events = POLLPRI;
fds[2].events = POLLPRI;

read(fd_btn1, &value, 1);
read(fd_left, &value, 1);
read(fd_right, &value, 1);

ret = poll(fds, 1, 10000);
//debugging purpose
printf("ret: %i - revents[0]: %i", ret, fds[0].revents);

In case button was pressed (interrupt triggered): ret=1d, revents=10d

In case nothing was pressed, both is 0d

oz123
  • 27,559
  • 27
  • 125
  • 187
Flitzpiepe
  • 167
  • 2
  • 8

1 Answers1

8

I've found some answer alluding to your question at: http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/t/182883

I just ran into the POLLERR thing you're seeing too. Turns out this is how all sysfs files work, and you're using gpio through the sysfs interface.

From the sysfs GPIO kernel document: If the pin can be configured as interrupt-generating interrupt and if it has been configured to generate interrupts (see the description of "edge"), you can poll(2) on that file and poll(2) will return whenever the interrupt was triggered. If you use poll(2), set the events POLLPRI and POLLERR. Also, if you look take a look at the kernel code in fs/sysfs/file.c, you'll see that sysfs_poll returns DEFAULT_POLLMASK | POLLERR | POLLPRI.

All that said, it does seem strange that sysfs files return POLLERR, I'm not sure why they chose to do that.

Slava
  • 96
  • 1
  • In linux, this seems to be done in the kernfs_fop_poll function in fs/kernfs/file.c. It simply always sets POLLERR for anything in sysfs. Also, https://www.kernel.org/doc/Documentation/gpio/sysfs.txt have a bit of info, though not particularly about POLLERR. – nos Jan 07 '15 at 11:27
  • I did some digging and I think I figured it out: the `POLLERR` is an implementation choice leaking through (because `poll` and `select` are wrappers around the same kernel API), not the result of intentional design decisions about what's best for the `poll` interface. See [the original commit that added this feature for sysfs files](https://github.com/torvalds/linux/commit/4508a7a734b111b8b7e39986237d84acb1168dd0) and the "Correspondence between select() and poll() notifications" section in [the `select` manpage](https://www.man7.org/linux/man-pages/man2/select.2.html). – mtraceur Oct 11 '22 at 18:17
  • Basically, it looks like returning `POLLERR|POLLPRI` was the smallest number of `poll` event bits that would cause the `select` system call to return regardless of which file descriptor sets the sysfs file was in. – mtraceur Oct 11 '22 at 18:23
  • (This is why people shouldn't be allowed to do too much low-level development without enough higher-level API development to balance it out - it damages the brain into tunnel-visioning on "what's the smallest change that achieves the behavior I want" and "what's the change that makes the most sense in the bowels of the implementation" and never asking "but does this result in an interface that best expresses the 'semantics' - the big-picture idea - the intent that *the user* has when reaching for this feature?") – mtraceur Oct 11 '22 at 18:31
  • The most charitable perspective is that 1) there was literally no better set of bits which *both* caused `select` to signal the FD as ready regardless of what FD set it was in *and* wasn't actively misleading when returned as-is from `poll` and 2) there was no great way to have `poll` omit that `POLLERR` or otherwise change the event bits in the poll set before returning it to userspace. – mtraceur Oct 11 '22 at 19:14
  • Ultimately the question to ask here is: if the kernel code paths for `poll` didn't also effect `select`, would anyone think that `POLLERR` was a sensible way to say "this magic file has changed" (or "you should re-open and re-read this magic file to get the latest contents now")? Judging by the number of questions where people express confusion about `POLLERR`, I think the answer is probably no, but I could see a reach/stretch argument for "this file needs to be *re-opened* to get the latest contents" being a sufficiently exceptional situation to warrant the `POLLERR` flag. – mtraceur Oct 11 '22 at 19:20