/*
 * 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);
}
Exemple #2
0
/*
 * 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);
}
Exemple #3
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);
	}
}