/* * The port_close_fd() function dissociates a file descriptor from a port * and removes all allocated resources. * close(2) detects in the uf_entry_t structure that the fd is associated * with a port (at least one port). * The fd can be associated with several ports. */ void port_close_pfd(portfd_t *pfd) { port_t *pp; port_fdcache_t *pcp; /* * the portfd_t passed in should be for this proc. */ ASSERT(curproc->p_pid == PFTOD(pfd)->pd_portev->portkev_pid); pp = PFTOD(pfd)->pd_portev->portkev_port; pcp = pp->port_queue.portq_pcp; mutex_enter(&pcp->pc_lock); (void) port_remove_fd_object(pfd, pp, pcp); mutex_exit(&pcp->pc_lock); }
/* * The port_dissociate_fd() function dissociates the delivered file * descriptor from the event port and removes already fired events. * If a fd is shared between processes, all involved processes will get * the same rights related to re-association of the fd with the port and * retrieve of events from that fd. * The process which associated the fd with a port for the first time * becomes also the owner of the association. Only the owner of the * association is allowed to dissociate the fd from the port. */ int port_dissociate_fd(port_t *pp, uintptr_t object) { int fd; port_fdcache_t *pcp; portfd_t *pfd; file_t *fp; if (object > (uintptr_t)INT_MAX) return (EBADFD); fd = object; pcp = pp->port_queue.portq_pcp; mutex_enter(&pcp->pc_lock); if (pcp->pc_hash == NULL) { /* no file descriptor cache available */ mutex_exit(&pcp->pc_lock); return (0); } if ((fp = getf(fd)) == NULL) { mutex_exit(&pcp->pc_lock); return (EBADFD); } pfd = port_cache_lookup_fp(pcp, fd, fp); if (pfd == NULL) { releasef(fd); mutex_exit(&pcp->pc_lock); return (0); } /* only association owner is allowed to remove the association */ if (curproc->p_pid != PFTOD(pfd)->pd_portev->portkev_pid) { releasef(fd); mutex_exit(&pcp->pc_lock); return (EACCES); } /* remove port from the file descriptor interested list */ delfd_port(fd, pfd); releasef(fd); /* remove polldat & port event structure */ port_remove_fd_object(pfd, pp, pcp); mutex_exit(&pcp->pc_lock); return (0); }
/* * The port_remove_portfd() function dissociates the port from the fd * and vive versa. */ static void port_remove_portfd(polldat_t *pdp, port_fdcache_t *pcp) { port_t *pp; file_t *fp; ASSERT(MUTEX_HELD(&pcp->pc_lock)); pp = pdp->pd_portev->portkev_port; fp = getf(pdp->pd_fd); /* * If we did not get the fp for pd_fd but its portfd_t * still exist in the cache, it means the pd_fd is being * closed by some other thread which will also free the portfd_t. */ if (fp != NULL) { delfd_port(pdp->pd_fd, PDTOF(pdp)); releasef(pdp->pd_fd); port_remove_fd_object(PDTOF(pdp), pp, pcp); } }