예제 #1
0
파일: ipc_object.c 프로젝트: CptFrazz/xnu
kern_return_t
ipc_object_copyin(
	ipc_space_t		space,
	mach_port_name_t	name,
	mach_msg_type_name_t	msgt_name,
	ipc_object_t		*objectp)
{
	ipc_entry_t entry;
	ipc_port_t soright;
	ipc_port_t release_port;
	kern_return_t kr;
	queue_head_t links_data;
	queue_t links = &links_data;
	wait_queue_link_t wql;

	queue_init(links);

	/*
	 *	Could first try a read lock when doing
	 *	MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
	 *	and MACH_MSG_TYPE_MAKE_SEND_ONCE.
	 */

	kr = ipc_right_lookup_write(space, name, &entry);
	if (kr != KERN_SUCCESS)
		return kr;
	/* space is write-locked and active */

	release_port = IP_NULL;
	kr = ipc_right_copyin(space, name, entry,
			      msgt_name, TRUE,
			      objectp, &soright,
			      &release_port,
			      links);
	if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
		ipc_entry_dealloc(space, name, entry);
	is_write_unlock(space);

	while(!queue_empty(links)) {
		wql = (wait_queue_link_t) dequeue(links);
		wait_queue_link_free(wql);
	}

	if (release_port != IP_NULL)
		ip_release(release_port);

	if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
		ipc_notify_port_deleted(soright, name);

	return kr;
}
예제 #2
0
파일: ipc_pset.c 프로젝트: andrekandore/xnu
static int
filt_machportattach(
        struct knote *kn)
{
        mach_port_name_t        name = (mach_port_name_t)kn->kn_kevent.ident;
	wait_queue_link_t	wql = wait_queue_link_allocate();
        ipc_pset_t              pset = IPS_NULL;
        int                     result = ENOSYS;
        kern_return_t           kr;

        kr = ipc_object_translate(current_space(), name,
                                  MACH_PORT_RIGHT_PORT_SET,
                                  (ipc_object_t *)&pset);
        if (kr != KERN_SUCCESS) {
		wait_queue_link_free(wql);
                return (kr == KERN_INVALID_NAME ? ENOENT : ENOTSUP);
        }
        /* We've got a lock on pset */

	/* 
	 * Bind the portset wait queue directly to knote/kqueue.
	 * This allows us to just use wait_queue foo to effect a wakeup,
	 * rather than having to call knote() from the Mach code on each
	 * message.
	 */
	result = knote_link_wait_queue(kn, &pset->ips_messages.imq_wait_queue, wql);
	if (result == 0) {
		/* keep a reference for the knote */
		kn->kn_ptr.p_pset = pset; 
		ips_reference(pset);
		ips_unlock(pset);
		return 0;
	}

	ips_unlock(pset);
	wait_queue_link_free(wql);
	return result;
}
예제 #3
0
파일: ipc_pset.c 프로젝트: andrekandore/xnu
static void
filt_machportdetach(
        struct knote *kn)
{
        ipc_pset_t              pset = kn->kn_ptr.p_pset;
	wait_queue_link_t	wql = WAIT_QUEUE_LINK_NULL;

	/*
	 * Unlink the portset wait queue from knote/kqueue,
	 * and release our reference on the portset.
	 */
	ips_lock(pset);
	(void)knote_unlink_wait_queue(kn, &pset->ips_messages.imq_wait_queue, &wql);
	kn->kn_ptr.p_pset = IPS_NULL;
	ips_unlock(pset);
	ips_release(pset);
	if (wql != WAIT_QUEUE_LINK_NULL)
		wait_queue_link_free(wql);
}
예제 #4
0
파일: ipc_pset.c 프로젝트: andrekandore/xnu
void
ipc_pset_destroy(
	ipc_pset_t	pset)
{
	spl_t		s;
	queue_head_t link_data;
	queue_t links = &link_data;
	wait_queue_link_t wql;

	queue_init(links);

	assert(ips_active(pset));

	pset->ips_object.io_bits &= ~IO_BITS_ACTIVE;

	/*
	 * remove all the member message queues
	 */
	ipc_mqueue_remove_all(&pset->ips_messages, links);
	
	/*
	 * Set all waiters on the portset running to
	 * discover the change.
	 */
	s = splsched();
	imq_lock(&pset->ips_messages);
	ipc_mqueue_changed(&pset->ips_messages);
	imq_unlock(&pset->ips_messages);
	splx(s);

	ips_unlock(pset);
	ips_release(pset);       /* consume the ref our caller gave us */

	while(!queue_empty(links)) {
		wql = (wait_queue_link_t) dequeue(links);
		wait_queue_link_free(wql);
	}

}