Exemplo n.º 1
0
/*
 * Return port event back to the kmem_cache.
 * If the event is currently in the port queue the event itself will only
 * be set as invalid. The port_get(n) function will not deliver such events
 * to the application and it will return them back to the kmem_cache.
 */
void
port_free_event(port_kevent_t *pkevp)
{
	port_queue_t	*portq;
	port_t		*pp;

	pp = pkevp->portkev_port;
	if (pp == NULL)
		return;
	if (pkevp->portkev_flags & PORT_ALLOC_PRIVATE) {
		port_free_event_local(pkevp, 0);
		return;
	}

	portq = &pp->port_queue;
	mutex_enter(&portq->portq_mutex);
	port_block(portq);
	if (pkevp->portkev_flags & PORT_KEV_DONEQ) {
		pkevp->portkev_flags |= PORT_KEV_FREE;
		pkevp->portkev_callback = NULL;
		port_unblock(portq);
		mutex_exit(&portq->portq_mutex);
		return;
	}
	port_unblock(portq);

	if (pkevp->portkev_flags & PORT_KEV_CACHED) {
		mutex_exit(&portq->portq_mutex);
		return;
	}

	if (--pp->port_curr < pp->port_max_events)
		cv_signal(&pp->port_cv);
	if (portq->portq_flags & PORTQ_CLOSE) {
		/*
		 * Another thread is closing the event port.
		 * That thread will sleep until all allocated event
		 * structures returned to the event port framework.
		 * The portq_mutex is used to synchronize the status
		 * of the allocated event structures (port_curr).
		 */
		if (pp->port_curr <= portq->portq_nent)
			cv_signal(&portq->portq_closecv);
	}
	mutex_exit(&portq->portq_mutex);
	port_free_event_local(pkevp, 1);
}
Exemplo 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);
}
Exemplo 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);
}