Print this page
pbchk
cleanup port_free_event_local() semantics

@@ -23,11 +23,11 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 /*
- * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
+ * Copyright 2020 Joyent, Inc.
  */
 
 #include <sys/types.h>
 #include <sys/vnode.h>
 #include <sys/vfs_opreg.h>

@@ -113,19 +113,29 @@
         port_kevent_t   *pkevp;
         int             events;         /* ignore events */
 
         mutex_enter(&portq->portq_mutex);
         while (pkevp = list_head(&portq->portq_list)) {
+                port_t *pp = pkevp->portkev_port;
+
                 portq->portq_nent--;
                 list_remove(&portq->portq_list, pkevp);
                 if (pkevp->portkev_callback) {
                         (void) (*pkevp->portkev_callback)(pkevp->portkev_arg,
                             &events, pkevp->portkev_pid, PORT_CALLBACK_CLOSE,
                             pkevp);
                 }
-                mutex_exit(&portq->portq_mutex);
-                port_free_event_local(pkevp, 0);
+                /*
+                 * Don't drop the portq_mutex, but instead perform the
+                 * decrement of port_curr in advance of calling
+                 * port_free_event_local().  We do need to reacquire
+                 * portq_mutex so we can properly wait for any
+                 * pollwakeup()-signalled threads to finish up.
+                 */
+                if (--pp->port_curr < pp->port_max_events)
+                        cv_signal(&pp->port_cv);
+                port_free_event_local(pkevp, B_FALSE);
                 mutex_enter(&portq->portq_mutex);
         }
 
         /*
          * Wait for any thread in pollwakeup(), accessing this port to