/* * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* * (pre-GNU) HISTORY * * Revision 2.4 91/05/14 17:53:15 mrt * Correcting copyright * * Revision 2.3 91/02/14 14:17:43 mrt * Added new Mach copyright * [91/02/13 12:44:15 mrt] * * Revision 2.2 90/08/06 17:24:22 rpd * Created. * */ #if 1 #include #else /* This is what CMU did, but that fails to declare some used functions. */ #include #include #include #endif static void mach_msg_destroy_port(mach_port_t, mach_msg_type_name_t); static void mach_msg_destroy_memory(vm_offset_t, vm_size_t); /* * Routine: mach_msg_destroy * Purpose: * Deallocates all port rights and out-of-line memory * found in a received message. */ void __mach_msg_destroy (mach_msg_header_t *msg) { mach_msg_bits_t mbits = msg->msgh_bits; /* * The msgh_local_port field doesn't hold a port right. * The receive operation consumes the destination port right. */ mach_msg_destroy_port(msg->msgh_remote_port, MACH_MSGH_BITS_REMOTE(mbits)); if (mbits & MACH_MSGH_BITS_COMPLEX) { #ifdef MACH_MSG_PORT_DESCRIPTOR mach_msg_body_t *body; mach_msg_descriptor_t *saddr, *eaddr; body = (mach_msg_body_t *) (msg + 1); saddr = (mach_msg_descriptor_t *) ((mach_msg_base_t *) msg + 1); eaddr = saddr + body->msgh_descriptor_count; for ( ; saddr < eaddr; saddr++) { switch (saddr->type.type) { case MACH_MSG_PORT_DESCRIPTOR: { mach_msg_port_descriptor_t *dsc; /* * Destroy port rights carried in the message */ dsc = &saddr->port; mach_msg_destroy_port(dsc->name, dsc->disposition); break; } case MACH_MSG_OOL_DESCRIPTOR : { mach_msg_ool_descriptor_t *dsc; /* * Destroy memory carried in the message */ dsc = &saddr->out_of_line; if (dsc->deallocate) { mach_msg_destroy_memory((vm_offset_t)dsc->address, dsc->size); } break; } case MACH_MSG_OOL_PORTS_DESCRIPTOR : { mach_port_t *ports; mach_msg_ool_ports_descriptor_t *dsc; mach_msg_type_number_t j; /* * Destroy port rights carried in the message */ dsc = &saddr->ool_ports; ports = (mach_port_t *) dsc->address; for (j = 0; j < dsc->count; j++, ports++) { mach_msg_destroy_port(*ports, dsc->disposition); } /* * Destroy memory carried in the message */ if (dsc->deallocate) { mach_msg_destroy_memory((vm_offset_t)dsc->address, dsc->count * sizeof(mach_port_t)); } break; } } } #else vm_offset_t saddr; vm_offset_t eaddr; saddr = (vm_offset_t) (msg + 1); eaddr = (vm_offset_t) msg + msg->msgh_size; while (saddr < eaddr) { mach_msg_type_long_t *type; mach_msg_type_name_t name; mach_msg_type_size_t size; mach_msg_type_number_t number; boolean_t is_inline; vm_size_t length; vm_offset_t addr; type = (mach_msg_type_long_t *) saddr; is_inline = type->msgtl_header.msgt_inline; if (type->msgtl_header.msgt_longform) { name = type->msgtl_name; size = type->msgtl_size; number = type->msgtl_number; saddr += sizeof(mach_msg_type_long_t); } else { name = type->msgtl_header.msgt_name; size = type->msgtl_header.msgt_size; number = type->msgtl_header.msgt_number; saddr += sizeof(mach_msg_type_t); } /* calculate length of data in bytes, rounding up */ length = (((((number * size) + 7) >> 3) + sizeof (int) - 1) &~ (sizeof (int) - 1)); addr = is_inline ? saddr : * (vm_offset_t *) saddr; if (MACH_MSG_TYPE_PORT_ANY(name)) { mach_port_t *ports = (mach_port_t *) addr; mach_msg_type_number_t i; for (i = 0; i < number; i++) mach_msg_destroy_port(*ports++, name); } if (is_inline) { /* inline data sizes round up to int boundaries */ saddr += length; } else { mach_msg_destroy_memory(addr, length); saddr += sizeof(vm_offset_t); } } #endif } } weak_alias (__mach_msg_destroy, mach_msg_destroy) static void mach_msg_destroy_port (mach_port_t port, mach_msg_type_name_t type) { if (MACH_PORT_VALID(port)) switch (type) { case MACH_MSG_TYPE_MOVE_SEND: case MACH_MSG_TYPE_MOVE_SEND_ONCE: /* destroy the send/send-once right */ (void) __mach_port_deallocate(mach_task_self(), port); break; case MACH_MSG_TYPE_MOVE_RECEIVE: /* destroy the receive right */ (void) __mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1); break; case MACH_MSG_TYPE_MAKE_SEND: /* create a send right and then destroy it */ (void) __mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); (void) __mach_port_deallocate(mach_task_self(), port); break; case MACH_MSG_TYPE_MAKE_SEND_ONCE: /* create a send-once right and then destroy it */ (void) __mach_port_extract_right(mach_task_self(), port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &port, &type); (void) __mach_port_deallocate(mach_task_self(), port); break; } } static void mach_msg_destroy_memory (vm_offset_t addr, vm_size_t size) { if (size > 0) (void) __vm_deallocate(__mach_task_self(), addr, size); }