/* ??? ports Copyright 1999, 2000, 2001 Johan Rydberg, jrydberg@opencores.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if 0 #include "cpus.h" #include #include "ipc/object.h" #include "ipc/port.h" #include "ipc/kmsg.h" #include "ipc/entry.h" #include "kern/queue.h" #include "kern/gdb.h" #include "kern/thread.h" #include "vm/vm-zone.h" /* Memory pool for portals. */ vm_zone_t ipc_port_zone; /* Template portal (for faster creation of portals). */ ipc_port template_port; #ifndef NPORTS #define NPORTS 256 #endif void ipc_port_init (void) { ipc_port_zone = vm_zone_create(sizeof (struct ipc_port), NPORTS, TRUE); /* Create template portal */ template_port = (ipc_port) vm_zone_alloc (ipc_port_zone); /* template_port->msg_queue (later) */ /* template_port->lock (later) */ template_port->ref_count = 1; template_port->pset = 0; template_port->active = true; template_port->is_pset = false; } kern_return_t ipc_port_create (out_port) ipc_port *out_port; { ipc_port port; port = (ipc_port) vm_zone_alloc (ipc_port_zone); if (port == 0) return KERN_RESOURCE_SHORTAGE; *port = *template_port; /* Initialize lock and message queue. */ simple_lock_init (&port->lock); port->mqueue = ipc_mqueue_create (); port->tqw = ipc_tqueue_create (); port->tqb = ipc_tqueue_create (); /* Return port */ *out_port = port; return KERN_SUCCESS; } kern_return_t ipc_port_create_receive (portp, object) ipc_port *portp; ipc_object object; { kern_return_t kr; ipc_port port; kr = ipc_port_create (&port); if (kr != KERN_SUCCESS) return kr; port->rcvobject = object; *portp = port; return KERN_SUCCESS; } kern_return_t ipc_port_create_kernel (portp) ipc_port *portp; { kern_return_t kr; ipc_port port; kr = ipc_port_create (&port); if (kr != KERN_SUCCESS) return kr; port->rcvobject = kernel_task->itc_object; *portp = port; return KERN_SUCCESS; } void ipc_port_reference (ip) ipc_port ip; { ip->ref_count++; } kern_return_t port_allocate (task, portp) task_t task; ipc_port *portp; { ipc_port port; ipc_port_create (&port); *portp = port; return KERN_SUCCESS; } kern_return_t port_allocate_name (task, name) task_t task; rtmk_port_t name; { kern_return_t kr; ipc_entry entry; ipc_port port; bool result; kr = ipc_port_create_receive (&port, task->itc_object); if (kr != KERN_SUCCESS) return kr; result = ipc_reserve_entry_named (task->itc_object, entry, port, name); if (result == false) return KERN_FAILURE; return KERN_SUCCESS; } kern_return_t port_deallocate (task, name) task_t task; rtmk_port_t name; { } ipc_port ipc_port_make_receive (ip, object) ipc_port ip; ipc_object object; { ipc_port rright; if (!IP_VALID (ip)) return IP_DEAD; simple_lock (&ip->lock); if (ip->active == true) { ipc_port_reference (ip); ip->rcvobject = object; rright = ip; } else rright = IP_DEAD; simple_unlock (&ip->lock); return rright; } ipc_port ipc_port_copy_send (ip) ipc_port ip; { ipc_port sright; if (!IP_VALID (ip)) return IP_DEAD; simple_lock (&ip->lock); if (ip->active == true) { ipc_port_reference (ip); ip->srights++; sright = ip; } else sright = IP_DEAD; simple_unlock (&ip->lock); return sright; } rtmk_port_t ipc_port_copyout_send (object, ip) ipc_object object; ipc_port ip; { rtmk_port_t name; kern_return_t kr; assert (IP_VALID (ip)); kr = ipc_object_copyout (object, ip, RTMK_PORT_TYPE_SEND, &name); if (kr != KERN_SUCCESS) { /* XXX should release or something here */ return 0; } return name; } /* Tries to insert send rights for PORT into TASK. Current task must have receive rights for PORT. Name is returned in NAMEP. */ kern_return_t port_insert_send_rights (target, port, namep) task_t target; ipc_port port; rtmk_port_t *namep; { return ipc_object_copyout (target->itc_object, port, RTMK_MSG_TYPE_MAKE_SEND, namep); } /* Create a port set. */ kern_return_t port_set_allocate (task, portp) task_t task; ipc_port *portp; { kern_return_t kr; ipc_port port; kr = ipc_port_create (&port); if (kr != KERN_SUCCESS) return kr; queue_init (&port->ports); port->is_pset = true; *portp = port; return KERN_SUCCESS; } /* Insert PORT into PSET. TASK must have receive rights for both PSET and PORT. */ kern_return_t port_set_insert_member (task, pset, port) task_t task; ipc_port pset, port; { simple_lock (&pset->lock); simple_lock (&port->lock); /* Check so that it's really a port set. */ if (pset->is_pset == false) return KERN_INVALID_ARGUMENT; /* See so that the port is not already in another port set. */ if (port->pset != 0 && port->pset != pset) return KERN_FAILURE; /* We move all messages from port to PORT to PSET mqueue. */ ipc_mqueue_move (pset->mqueue, port->mqueue); ipc_mqueue_destroy (port->mqueue); port->mqueue = pset->mqueue; /* We destroy the thread queue aswell. XXX more threads here??? */ ipc_tqueue_destroy (port->tqw); port->tqw = pset->tqw; /* XXX tqb ?? */ /* Record port in port set. */ enqueue_tail (&pset->ports, &port->link); port->pset = pset; simple_unlock (&port->lock); simple_unlock (&pset->lock); return KERN_SUCCESS; } #endif