/* * 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. */ /* * HISTORY * $Log$ * Revision 1.6 2002/02/17 07:13:36 roland * 2002-02-16 Roland McGrath * * * mach/msg-destroy.c (__mach_msg_destroy) [MACH_MSG_PORT_DESCRIPTOR]: * Grok the OSF flavor of message format. * (mach_msg_destroy_port): For MAKE_SEND and * MAKE_SEND_ONCE rights, create an destroy a right to ensure proper * no-senders notification. * * Revision 1.5 1997/06/21 01:40:07 drepper * More 64bit changes. * * Revision 1.4 1996/11/15 19:44:43 thomas * Tue Nov 12 16:58:41 1996 Thomas Bushnell, n/BSG * * * mach/mach.h (__mach_msg_destroy, mach_msg_destroy, __mach_msg): * Provide prototypes. * * * mach/msg-destroy.c (mach_msg_destroy_port, * mach_msg_destroy_memory): Use prototype syntax. * * hurd/hurdmalloc.c (more_memory, malloc_fork_prepare, * malloc_fork_parent, malloc_fork_child): Likewise. * * Revision 1.3 1995/01/23 22:16:52 roland * (mach_msg_destroy): Define as weak alias for __mach_msg_destroy. * * Revision 1.2 1993/08/03 06:13:18 roland * entered into RCS * * 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(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); }