Exemple #1
0
/*
 * fileport_alloc
 *
 * Description: Obtain a send right for the given fileglob, which must be
 *		referenced.
 *
 * Parameters: 	fg		A fileglob.
 *
 * Returns: 	Port of type IKOT_FILEPORT with fileglob set as its kobject. 
 * 		Port is returned with a send right.
 */
ipc_port_t
fileport_alloc(struct fileglob *fg)
{
	ipc_port_t fileport;
	ipc_port_t sendport;
	ipc_port_t notifyport;

	fileport = ipc_port_alloc_kernel();
	if (fileport == IP_NULL) {
		goto out;
	}

	ipc_kobject_set(fileport, (ipc_kobject_t)fg, IKOT_FILEPORT);
	notifyport = ipc_port_make_sonce(fileport);
	ip_lock(fileport); /* unlocked by ipc_port_nsrequest */
	ipc_port_nsrequest(fileport, 1, notifyport, &notifyport);

	sendport = ipc_port_make_send(fileport);
	if (!IP_VALID(sendport)) {
		panic("Couldn't allocate send right for fileport!\n");
	}

out:
	return fileport;
}
Exemple #2
0
EXTERN ipc_port_t
iokit_alloc_object_port( io_object_t obj, ipc_kobject_type_t type )
{
    ipc_port_t		notify;
    ipc_port_t		port;

    do {

	/* Allocate port, keeping a reference for it. */
        port = ipc_port_alloc_kernel();
        if( port == IP_NULL)
            continue;

        /* set kobject & type */
//	iokit_add_reference( obj );
	ipc_kobject_set( port, (ipc_kobject_t) obj, type);

        /* Request no-senders notifications on the port. */
        ip_lock( port);
        notify = ipc_port_make_sonce_locked( port);
        ipc_port_nsrequest( port, 1, notify, &notify);
	/* port unlocked */
        assert( notify == IP_NULL);
	gIOKitPortCount++;

    } while( FALSE);

    return( port );
}
Exemple #3
0
/*
 *	Routine:	convert_mig_object_to_port [interface]
 *	Purpose:
 *		Base implementation of MIG outtrans routine to convert from
 *		a mig object reference to a new send right on the object's
 *		port.  The object reference is consumed.
 *	Returns:
 *		IP_NULL - Null MIG object supplied
 *		Otherwise, a newly made send right for the port
 *	Conditions:
 *		Nothing locked.
 */
ipc_port_t
convert_mig_object_to_port(
	mig_object_t	mig_object)
{
	ipc_port_t	port;
	boolean_t	deallocate = TRUE;

	if (mig_object == MIG_OBJECT_NULL)
		return IP_NULL;

	port = mig_object->port;
	while ((port == IP_NULL) ||
	       ((port = ipc_port_make_send(port)) == IP_NULL)) {
		ipc_port_t	previous;

		/*
		 * Either the port was never set up, or it was just
		 * deallocated out from under us by the no-senders
		 * processing.  In either case, we must:
		 *	Attempt to make one
		 * 	Arrange for no senders
		 *	Try to atomically register it with the object
		 *		Destroy it if we are raced.
		 */
		port = ipc_port_alloc_kernel();
		ip_lock(port);
		ipc_kobject_set_atomically(port,
					   (ipc_kobject_t) mig_object,
					   IKOT_MIG);

		/* make a sonce right for the notification */
		port->ip_sorights++;
		ip_reference(port);

		ipc_port_nsrequest(port, 1, port, &previous);
		/* port unlocked */

		assert(previous == IP_NULL);

		if (OSCompareAndSwapPtr((void *)IP_NULL, (void *)port,
											(void * volatile *)&mig_object->port)) {
			deallocate = FALSE;
		} else {
			ipc_port_dealloc_kernel(port);
			port = mig_object->port;
		}
	}

	if (deallocate)
		mig_object->pVtbl->Release((IMIGObject *)mig_object);

	return (port);
}
Exemple #4
0
boolean_t
mig_object_no_senders(
	ipc_port_t		port,
	mach_port_mscount_t	mscount)
{
	mig_object_t		mig_object;

	ip_lock(port);
	if (port->ip_mscount > mscount) {
		ipc_port_t 	previous;

		/*
		 * Somebody created new send rights while the
		 * notification was in-flight.  Just create a
		 * new send-once right and re-register with 
		 * the new (higher) mscount threshold.
		 */
		/* make a sonce right for the notification */
		port->ip_sorights++;
		ip_reference(port);
		ipc_port_nsrequest(port, mscount, port, &previous);
		/* port unlocked */

		assert(previous == IP_NULL);
		return (FALSE);
	}

	/*
	 * Clear the port pointer while we have it locked.
	 */
	mig_object = (mig_object_t)port->ip_kobject;
	mig_object->port = IP_NULL;

	/*
	 * Bring the sequence number and mscount in
	 * line with ipc_port_destroy assertion.
	 */
	port->ip_mscount = 0;
	port->ip_messages.imq_seqno = 0;
	ipc_port_destroy(port); /* releases lock */
	
	/*
	 * Release the port's reference on the object.
	 */
	mig_object->pVtbl->Release((IMIGObject *)mig_object);
	return (TRUE);
}	
Exemple #5
0
static void
iokit_no_senders( mach_no_senders_notification_t * notification )
{
    ipc_port_t		port;
    io_object_t		obj = NULL;
    ipc_kobject_type_t	type = IKOT_NONE;
    ipc_port_t		notify;

    port = (ipc_port_t) notification->not_header.msgh_remote_port;

    // convert a port to io_object_t.
    if( IP_VALID(port)) {
        iokit_lock_port(port);
        if( ip_active(port)) {
            obj = (io_object_t) port->ip_kobject;
	    type = ip_kotype( port );
            if( (IKOT_IOKIT_OBJECT  == type)
	     || (IKOT_IOKIT_CONNECT == type))
                iokit_add_reference( obj );
            else
                obj = NULL;
	}
        iokit_unlock_port(port);

        if( obj ) {

	    mach_port_mscount_t mscount = notification->not_count;

            if( KERN_SUCCESS != iokit_client_died( obj, port, type, &mscount ))
	    {
		/* Re-request no-senders notifications on the port (if still active) */
		ip_lock(port);
		if (ip_active(port)) {
			notify = ipc_port_make_sonce_locked(port);
			ipc_port_nsrequest( port, mscount + 1, notify, &notify);
			/* port unlocked */
			if ( notify != IP_NULL)
				ipc_port_release_sonce(notify);
		} else {
			ip_unlock(port);
		}
	    }
            iokit_remove_reference( obj );
        }
    }
}
Exemple #6
0
/*
 *	Routine:	convert_semaphore_to_port
 *	Purpose:
 *		Convert a semaphore reference to a send right to a
 *		semaphore port.
 *
 *		Consumes the semaphore reference.  If the semaphore
 *		port currently has no send rights (or doesn't exist
 *		yet), the reference is donated to the port to represent
 *		all extant send rights collectively.
 */
ipc_port_t
convert_semaphore_to_port (semaphore_t semaphore)
{
	ipc_port_t port, send;

	if (semaphore == SEMAPHORE_NULL)
		return (IP_NULL);

	/* caller is donating a reference */
	port = semaphore->port;

	if (!IP_VALID(port)) {
		port = ipc_port_alloc_kernel();
		assert(IP_VALID(port));
		ipc_kobject_set_atomically(port, (ipc_kobject_t) semaphore, IKOT_SEMAPHORE);

		/* If we lose the race, deallocate and pick up the other guy's port */
		if (!OSCompareAndSwapPtr(IP_NULL, port, &semaphore->port)) {
			ipc_port_dealloc_kernel(port);
			port = semaphore->port;
			assert(ip_kotype(port) == IKOT_SEMAPHORE);
			assert(port->ip_kobject == (ipc_kobject_t)semaphore);
		}
	}

	ip_lock(port);
	assert(ip_active(port));
	send = ipc_port_make_send_locked(port);

	if (1 == port->ip_srights) {
		ipc_port_t old_notify;

		/* transfer our ref to the port, and arm the no-senders notification */
		assert(IP_NULL == port->ip_nsrequest);
		ipc_port_nsrequest(port, port->ip_mscount, ipc_port_make_sonce_locked(port), &old_notify);
		/* port unlocked */
		assert(IP_NULL == old_notify);
	} else {
		/* piggyback on the existing port reference, so consume ours */
		ip_unlock(port);
		semaphore_dereference(semaphore);
	}
	return (send);
}
Exemple #7
0
kern_return_t
mach_port_request_notification(
	ipc_space_t		space,
	mach_port_name_t	name,
	mach_msg_id_t		id,
	mach_port_mscount_t	sync,
	ipc_port_t		notify,
	ipc_port_t		*previousp)
{
	kern_return_t kr;
	ipc_entry_t entry;	
	ipc_port_t port;
	

	if (space == IS_NULL)
		return KERN_INVALID_TASK;

	if (notify == IP_DEAD)
		return KERN_INVALID_CAPABILITY;

#if	NOTYET
	/*
	 *	Requesting notifications on RPC ports is an error.
	 */
	kr = ipc_right_lookup_write(space, name, &entry);	
	if (kr != KERN_SUCCESS)
		return kr;

	port = (ipc_port_t) entry->ie_object;

	if (port->ip_subsystem != NULL) {
		is_write_unlock(space);
		panic("mach_port_request_notification: on RPC port!!"); 
		return KERN_INVALID_CAPABILITY;
	}
	is_write_unlock(space);
#endif 	/* NOTYET */


	switch (id) {
	    case MACH_NOTIFY_PORT_DESTROYED: {
		ipc_port_t port, previous;

		if (sync != 0)
			return KERN_INVALID_VALUE;

		if (!MACH_PORT_VALID(name))
			return KERN_INVALID_RIGHT;

		kr = ipc_port_translate_receive(space, name, &port);
		if (kr != KERN_SUCCESS)
			return kr;
		/* port is locked and active */

		ipc_port_pdrequest(port, notify, &previous);
		/* port is unlocked */

		*previousp = previous;
		break;
	    }

	    case MACH_NOTIFY_NO_SENDERS: {
		ipc_port_t port;

		if (!MACH_PORT_VALID(name))
			return KERN_INVALID_RIGHT;

		kr = ipc_port_translate_receive(space, name, &port);
		if (kr != KERN_SUCCESS)
			return kr;
		/* port is locked and active */

		ipc_port_nsrequest(port, sync, notify, previousp);
		/* port is unlocked */
		break;
	    }

	    case MACH_NOTIFY_DEAD_NAME:

	    	if (!MACH_PORT_VALID(name)) {
			/*
			 * Already dead.
			 * Should do immediate delivery check -
			 * will do that in the near future.
			 */
	      		return KERN_INVALID_ARGUMENT;
		}

		kr = ipc_right_dnrequest(space, name, sync != 0,
					 notify, previousp);
		if (kr != KERN_SUCCESS)
			return kr;
		break;

	    default:
		return KERN_INVALID_VALUE;
	}

	return KERN_SUCCESS;
}
Exemple #8
0
Fichier : net.c Projet : ctos/bpi
static io_return_t
device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type,
	     dev_mode_t mode, char *name, device_t *devp)
{
  io_return_t err = D_SUCCESS;
  ipc_port_t notify;
  struct ifnet *ifp;
  struct linux_device *dev;
  struct net_data *nd;

  /* Search for the device.  */
  for (dev = dev_base; dev; dev = dev->next)
    if (dev->base_addr
	&& dev->base_addr != 0xffe0
	&& !strcmp (name, dev->name))
      break;
  if (!dev)
    return D_NO_SUCH_DEVICE;

  /* Allocate and initialize device data if this is the first open.  */
  nd = dev->net_data;
  if (!nd)
    {
      dev->net_data = nd = ((struct net_data *)
			    kalloc (sizeof (struct net_data)));
      if (!nd)
	{
	  err = D_NO_MEMORY;
	  goto out;
	}
      nd->dev = dev;
      nd->device.emul_data = nd;
      nd->device.emul_ops = &linux_net_emulation_ops;
      nd->port = ipc_port_alloc_kernel ();
      if (nd->port == IP_NULL)
	{
	  err = KERN_RESOURCE_SHORTAGE;
	  goto out;
	}
      ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE);
      notify = ipc_port_make_sonce (nd->port);
      ip_lock (nd->port);
      ipc_port_nsrequest (nd->port, 1, notify, &notify);
      assert (notify == IP_NULL);

      ifp = &nd->ifnet;
      ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0';
      ifp->if_flags = IFF_UP | IFF_RUNNING;
      ifp->if_mtu = dev->mtu;
      ifp->if_header_size = dev->hard_header_len;
      ifp->if_header_format = dev->type;
      ifp->if_address_size = dev->addr_len;
      ifp->if_address = dev->dev_addr;
      if_init_queues (ifp);

      if (dev->open)
	{
	  linux_intr_pri = SPL6;
	  if ((*dev->open) (dev))
	    err = D_NO_SUCH_DEVICE;
	}

    out:
      if (err)
	{
	  if (nd)
	    {
	      if (nd->port != IP_NULL)
		{
		  ipc_kobject_set (nd->port, IKO_NULL, IKOT_NONE);
		  ipc_port_dealloc_kernel (nd->port);
		}
	      kfree ((vm_offset_t) nd, sizeof (struct net_data));
	      nd = NULL;
	      dev->net_data = NULL;
	    }
	}
      else
	{
	  /* IPv6 heavily relies on multicasting (especially router and
	     neighbor solicits and advertisements), so enable reception of
	     those multicast packets by setting `LINUX_IFF_ALLMULTI'.  */
	  dev->flags |= LINUX_IFF_UP | LINUX_IFF_RUNNING | LINUX_IFF_ALLMULTI;
	  skb_queue_head_init (&dev->buffs[0]);

	  if (dev->set_multicast_list)
	    dev->set_multicast_list (dev);
	}
      if (IP_VALID (reply_port))
	ds_device_open_reply (reply_port, reply_port_type,
			      err, dev_to_port (nd));
      return MIG_NO_REPLY;
    }

  *devp = &nd->device;
  return D_SUCCESS;
}