| /* |
| * 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 <mach.h> |
| #else |
| /* This is what CMU did, but that fails to declare some used functions. */ |
| #include <mach/port.h> |
| #include <mach/message.h> |
| #include <mach_init.h> |
| #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(msg) |
| 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(port, type) |
| 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(addr, size) |
| vm_offset_t addr; |
| vm_size_t size; |
| { |
| if (size > 0) |
| (void) __vm_deallocate(__mach_task_self(), addr, size); |
| } |