Print this page
pbchk
cleanup port_free_event_local() semantics


   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/vnode.h>
  33 #include <sys/vfs_opreg.h>
  34 #include <sys/kmem.h>
  35 #include <fs/fs_subr.h>
  36 #include <sys/proc.h>
  37 #include <sys/kstat.h>
  38 #include <sys/port_impl.h>
  39 
  40 /* local functions */
  41 static int port_open(struct vnode **, int, cred_t *, caller_context_t *);
  42 static int port_close(struct vnode *, int, int, offset_t, cred_t *,
  43         caller_context_t *);
  44 static int port_getattr(struct vnode *, struct vattr *, int, cred_t *,
  45         caller_context_t *);
  46 static int port_access(struct vnode *, int, int, cred_t *, caller_context_t *);
  47 static int port_realvp(vnode_t *, vnode_t **, caller_context_t *);
  48 static int port_poll(vnode_t *, short, int, short *, struct pollhead **,


  98                                 kevp->portkev_flags |= PORT_KEV_FREE;
  99                 }
 100                 kevp = list_next(&portq->portq_list, kevp);
 101         }
 102         port_unblock(portq);
 103         mutex_exit(&portq->portq_mutex);
 104 }
 105 
 106 /*
 107  * Called from port_close().
 108  * Free all kernel events structures which are still in the event queue.
 109  */
 110 static void
 111 port_close_events(port_queue_t *portq)
 112 {
 113         port_kevent_t   *pkevp;
 114         int             events;         /* ignore events */
 115 
 116         mutex_enter(&portq->portq_mutex);
 117         while (pkevp = list_head(&portq->portq_list)) {


 118                 portq->portq_nent--;
 119                 list_remove(&portq->portq_list, pkevp);
 120                 if (pkevp->portkev_callback) {
 121                         (void) (*pkevp->portkev_callback)(pkevp->portkev_arg,
 122                             &events, pkevp->portkev_pid, PORT_CALLBACK_CLOSE,
 123                             pkevp);
 124                 }
 125                 mutex_exit(&portq->portq_mutex);
 126                 port_free_event_local(pkevp, 0);








 127                 mutex_enter(&portq->portq_mutex);
 128         }
 129 
 130         /*
 131          * Wait for any thread in pollwakeup(), accessing this port to
 132          * finish.
 133          */
 134         while (portq->portq_flags & PORTQ_POLLWK_PEND) {
 135                 cv_wait(&portq->portq_closecv, &portq->portq_mutex);
 136         }
 137         mutex_exit(&portq->portq_mutex);
 138 }
 139 
 140 /*
 141  * The port_close() function is called from standard close(2) when
 142  * the file descriptor is of type S_IFPORT/VPORT.
 143  * Port file descriptors behave like standard file descriptors. It means,
 144  * the port file/vnode is only destroyed on last close.
 145  * If the reference counter is > 1 then
 146  * - sources associated with the port will be notified about the close,




   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2020 Joyent, Inc.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/vnode.h>
  33 #include <sys/vfs_opreg.h>
  34 #include <sys/kmem.h>
  35 #include <fs/fs_subr.h>
  36 #include <sys/proc.h>
  37 #include <sys/kstat.h>
  38 #include <sys/port_impl.h>
  39 
  40 /* local functions */
  41 static int port_open(struct vnode **, int, cred_t *, caller_context_t *);
  42 static int port_close(struct vnode *, int, int, offset_t, cred_t *,
  43         caller_context_t *);
  44 static int port_getattr(struct vnode *, struct vattr *, int, cred_t *,
  45         caller_context_t *);
  46 static int port_access(struct vnode *, int, int, cred_t *, caller_context_t *);
  47 static int port_realvp(vnode_t *, vnode_t **, caller_context_t *);
  48 static int port_poll(vnode_t *, short, int, short *, struct pollhead **,


  98                                 kevp->portkev_flags |= PORT_KEV_FREE;
  99                 }
 100                 kevp = list_next(&portq->portq_list, kevp);
 101         }
 102         port_unblock(portq);
 103         mutex_exit(&portq->portq_mutex);
 104 }
 105 
 106 /*
 107  * Called from port_close().
 108  * Free all kernel events structures which are still in the event queue.
 109  */
 110 static void
 111 port_close_events(port_queue_t *portq)
 112 {
 113         port_kevent_t   *pkevp;
 114         int             events;         /* ignore events */
 115 
 116         mutex_enter(&portq->portq_mutex);
 117         while (pkevp = list_head(&portq->portq_list)) {
 118                 port_t *pp = pkevp->portkev_port;
 119 
 120                 portq->portq_nent--;
 121                 list_remove(&portq->portq_list, pkevp);
 122                 if (pkevp->portkev_callback) {
 123                         (void) (*pkevp->portkev_callback)(pkevp->portkev_arg,
 124                             &events, pkevp->portkev_pid, PORT_CALLBACK_CLOSE,
 125                             pkevp);
 126                 }
 127                 /*
 128                  * Don't drop the portq_mutex, but instead perform the
 129                  * decrement of port_curr in advance of calling
 130                  * port_free_event_local().  We do need to reacquire
 131                  * portq_mutex so we can properly wait for any
 132                  * pollwakeup()-signalled threads to finish up.
 133                  */
 134                 if (--pp->port_curr < pp->port_max_events)
 135                         cv_signal(&pp->port_cv);
 136                 port_free_event_local(pkevp, B_FALSE);
 137                 mutex_enter(&portq->portq_mutex);
 138         }
 139 
 140         /*
 141          * Wait for any thread in pollwakeup(), accessing this port to
 142          * finish.
 143          */
 144         while (portq->portq_flags & PORTQ_POLLWK_PEND) {
 145                 cv_wait(&portq->portq_closecv, &portq->portq_mutex);
 146         }
 147         mutex_exit(&portq->portq_mutex);
 148 }
 149 
 150 /*
 151  * The port_close() function is called from standard close(2) when
 152  * the file descriptor is of type S_IFPORT/VPORT.
 153  * Port file descriptors behave like standard file descriptors. It means,
 154  * the port file/vnode is only destroyed on last close.
 155  * If the reference counter is > 1 then
 156  * - sources associated with the port will be notified about the close,