Comment for patch 2.

+int
+rb_io_poll_fd(int fd, short events, int timeout)
+{
+    rb_fdset_t rfds, wfds, efds;
+    struct poll_select_args args;
+    struct timeval tv;
+    int r;
+    VALUE ptr = (VALUE)&args;
+
+    args.as.fd = fd;
+    args.read = (events & RB_POLLIN) ? init_set_fd(fd, &rfds) : NULL;
+    args.write = (events & RB_POLLOUT) ? init_set_fd(fd, &wfds) : NULL;
+    args.except = (events & RB_POLLPRI) ? init_set_fd(fd, &efds) : NULL;
+    args.tv = msec2tv(&tv, timeout);
+
+    r = (int)rb_ensure(poll_select, ptr, poll_select_cleanup, ptr);
+    if (r == -1)
+       errno = args.as.error;
+
+    return r;
+}

This is wrong abstranction.

- many platform use select even though the name is rb_io_poll_fd().
- select can treat usec, but this function only treat msec.
- this function only take one fd. but a name of poll imply multiple.

I'd suggest to make generic single fd waiting abstract function, like below.
  rb_wait_for_single_fd(int fd, int events, struct timeval *tv);

Also, RB_POLLIN should be avoided.

patch 3-7 looks good to me.