Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>

@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2017 Joyent, Inc.
  */
 
 
 /*
  * dcam.c

@@ -1038,72 +1039,58 @@
 
         return (rc);
 }
 
 
-/*
- * dcam_chpoll
- */
 /* ARGSUSED */
 int
 dcam_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
     struct pollhead **phpp)
 {
         dcam_state_t    *softc_p;
-        int              instance, ring_buff_has_data, read_ptr_id;
-        size_t           read_ptr_pos, write_ptr_pos;
-        short            revent;
+        int             instance;
+        short           revent = 0;
 
-        instance = DEV_TO_INSTANCE(dev);
+        /*
+         * Without the logic to perform wakeups (see comment below), reject
+         * attempts at edge-triggered polling.
+         */
+        if (events & POLLET) {
+                return (EPERM);
+        }
 
+        instance = DEV_TO_INSTANCE(dev);
         softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
         if (softc_p == NULL) {
                 return (ENXIO);
         }
 
-        read_ptr_id     = 0;
-        revent          = 0;
+        if (softc_p->ring_buff_p != NULL) {
+                size_t read_ptr_pos, write_ptr_pos;
 
-        if (softc_p->ring_buff_p == NULL) {
-                ring_buff_has_data = 0;
-        } else {
                 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
-
                 read_ptr_pos =
-                    ring_buff_read_ptr_pos_get(softc_p->ring_buff_p,
-                    read_ptr_id);
-
+                    ring_buff_read_ptr_pos_get(softc_p->ring_buff_p, 0);
                 write_ptr_pos =
                     ring_buff_write_ptr_pos_get(softc_p->ring_buff_p);
-
-                if (read_ptr_pos != write_ptr_pos) {
-                        ring_buff_has_data = 1;
-                } else {
-                        ring_buff_has_data = 0;
-                }
-
                 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
-        }
 
-        /*
-         * now check for events
-         */
-        if ((events & POLLRDNORM) && ring_buff_has_data) {
+                if ((events & POLLRDNORM) && read_ptr_pos != write_ptr_pos) {
                 revent |= POLLRDNORM;
         }
+        }
 
         if ((events & POLLPRI) && softc_p->param_status) {
                 revent |= POLLPRI;
         }
 
-        /* if no events have occurred */
-        if (revent == 0) {
-                if (!anyyet) {
-                        *phpp = &softc_p->dcam_pollhead;
-                }
-        }
-
+        /*
+         * No portion of this driver was ever wired up to perform a
+         * pollwakeup() on an associated pollhead.  The lack of an emitted
+         * pollhead informs poll/devpoll that the event status of this resource
+         * is not cacheable.
+         */
         *reventsp = revent;
 
         return (0);
 }