Ejemplo n.º 1
0
/* ARGSUSED */
static int
port_fd_callback(void *arg, int *events, pid_t pid, int flag, void *evp)
{
	portfd_t	*pfd = (portfd_t *)arg;
	polldat_t	*pdp = PFTOD(pfd);
	port_fdcache_t	*pcp;
	file_t		*fp;
	int		error;

	ASSERT((pdp != NULL) && (events != NULL));
	switch (flag) {
	case PORT_CALLBACK_DEFAULT:
		if (curproc->p_pid != pid) {
			/*
			 * Check if current process is allowed to retrieve
			 * events from this fd.
			 */
			fp = getf(pdp->pd_fd);
			if (fp == NULL) {
				error = EACCES; /* deny delivery of events */
				break;
			}
			releasef(pdp->pd_fd);
			if (fp != pdp->pd_fp) {
				error = EACCES; /* deny delivery of events */
				break;
			}
		}
		*events = pdp->pd_portev->portkev_events; /* update events */
		error = 0;
		break;
	case PORT_CALLBACK_DISSOCIATE:
		error = 0;
		break;
	case PORT_CALLBACK_CLOSE:
		/* remove polldat/portfd struct */
		pdp->pd_portev = NULL;
		pcp = (port_fdcache_t *)pdp->pd_pcache;
		mutex_enter(&pcp->pc_lock);
		pdp->pd_fp = NULL;
		pdp->pd_events = 0;
		if (pdp->pd_php != NULL) {
			pollhead_delete(pdp->pd_php, pdp);
			pdp->pd_php = NULL;
		}
		port_pcache_remove_fd(pcp, pfd);
		mutex_exit(&pcp->pc_lock);
		error = 0;
		break;
	default:
		error = EINVAL;
		break;
	}
	return (error);
}
Ejemplo n.º 2
0
/*
 * Remove the fd from the event port cache.
 */
static void
port_remove_fd_local(portfd_t *pfd, port_fdcache_t *pcp)
{
	polldat_t	*pdp = PFTOD(pfd);

	ASSERT(MUTEX_HELD(&pcp->pc_lock));
	pdp->pd_fp = NULL;
	if (pdp->pd_php != NULL) {
		pollhead_delete(pdp->pd_php, pdp);
		pdp->pd_php = NULL;
	}
	port_free_event_local(pdp->pd_portev, 0);
	/* remove polldat struct */
	port_pcache_remove_fd(pcp, pfd);
}
Ejemplo n.º 3
0
/*
 * The port_remove_fd_object() function frees all resources associated with
 * delivered portfd_t structure. Returns 1 if the port_kevent was found
 * and removed from the port queue.
 */
int
port_remove_fd_object(portfd_t *pfd, port_t *pp, port_fdcache_t *pcp)
{
	port_queue_t	*portq;
	polldat_t	*pdp = PFTOD(pfd);
	port_kevent_t	*pkevp;
	int		error;
	int		removed = 0;

	ASSERT(MUTEX_HELD(&pcp->pc_lock));
	if (pdp->pd_php != NULL) {
		pollhead_delete(pdp->pd_php, pdp);
		pdp->pd_php = NULL;
	}
	pkevp =  pdp->pd_portev;
	portq = &pp->port_queue;
	mutex_enter(&portq->portq_mutex);
	port_block(portq);
	if (pkevp->portkev_flags & PORT_KEV_DONEQ) {
		if (portq->portq_getn && portq->portq_tnent) {
			/*
			 * move events from the temporary "get" queue
			 * back to the port queue
			 */
			port_push_eventq(portq);
		}
		/* cleanup merged port queue */
		port_remove_event_doneq(pkevp, portq);
		removed = 1;
	}
	port_unblock(portq);
	mutex_exit(&portq->portq_mutex);
	if (pkevp->portkev_callback) {
		(void) (*pkevp->portkev_callback)(pkevp->portkev_arg,
		    &error, pkevp->portkev_pid, PORT_CALLBACK_DISSOCIATE,
		    pkevp);
	}
	port_free_event_local(pkevp, 0);

	/* remove polldat struct */
	port_pcache_remove_fd(pcp, pfd);
	return (removed);
}
Ejemplo n.º 4
0
/*
 * Associate event port polldat_t structure with sub-system pointer to
 * a polhead_t structure.
 */
static int
port_bind_pollhead(pollhead_t **php, polldat_t *pdp, short *revents)
{
	int		error;
	file_t		*fp;

	/*
	 * During re-association of a fd with a port the pd_php pointer
	 * is still the same as at the first association time.
	 */
	if (pdp->pd_php == *php)
		return (0);		/* already associated */

	/* polldat_t associated with another pollhead_t pointer */
	if (pdp->pd_php != NULL)
		pollhead_delete(pdp->pd_php, pdp);

	/*
	 * Before pollhead_insert() pollwakeup() will not detect a polldat
	 * entry in the ph_list and the event notification will disappear.
	 * This happens because polldat_t is still not associated with
	 * the pointer to the pollhead_t structure.
	 */
	pollhead_insert(*php, pdp);

	/*
	 * From now on event notification can be detected in pollwakeup(),
	 * Use VOP_POLL() again to check the current status of the event.
	 */
	pdp->pd_php = *php;
	fp = pdp->pd_fp;
	curthread->t_pollcache = (pollcache_t *)pdp->pd_pcache;
	error = VOP_POLL(fp->f_vnode, pdp->pd_events, 0, revents, php);
	curthread->t_pollcache = NULL;
	return (error);
}