6 * Mach Operating System
7 * Copyright (c) 1991,1990 Carnegie Mellon University
10 * Permission to use, copy, modify and distribute this software and its
11 * documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
20 * Carnegie Mellon requests users of this software to return to
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
31 #include <mach/mach.h>
32 #include <mach/message.h>
33 #include <mach/mach_init.h>
35 static void mach_msg_destroy_port(mach_port_t
, mach_msg_type_name_t
);
36 static void mach_msg_destroy_memory(vm_offset_t
, vm_size_t
);
39 * Routine: mach_msg_destroy
41 * mach_msg_destroy is useful in two contexts.
43 * First, it can deallocate all port rights and
44 * out-of-line memory in a received message.
45 * When a server receives a request it doesn't want,
46 * it needs this functionality.
48 * Second, it can mimic the side-effects of a msg-send
49 * operation. The effect is as if the message were sent
50 * and then destroyed inside the kernel. When a server
51 * can't send a reply (because the client died),
52 * it needs this functionality.
55 mach_msg_destroy(mach_msg_header_t
*msg
)
57 mach_msg_bits_t mbits
= msg
->msgh_bits
;
60 * The msgh_local_port field doesn't hold a port right.
61 * The receive operation consumes the destination port right.
64 mach_msg_destroy_port(msg
->msgh_remote_port
, MACH_MSGH_BITS_REMOTE(mbits
));
66 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
67 mach_msg_body_t
*body
;
68 mach_msg_descriptor_t
*saddr
, *eaddr
;
70 body
= (mach_msg_body_t
*) (msg
+ 1);
71 saddr
= (mach_msg_descriptor_t
*)
72 ((mach_msg_base_t
*) msg
+ 1);
73 eaddr
= saddr
+ body
->msgh_descriptor_count
;
75 for ( ; saddr
< eaddr
; saddr
++) {
76 switch (saddr
->type
.type
) {
78 case MACH_MSG_PORT_DESCRIPTOR
: {
79 mach_msg_port_descriptor_t
*dsc
;
82 * Destroy port rights carried in the message
85 mach_msg_destroy_port(dsc
->name
, dsc
->disposition
);
89 case MACH_MSG_OOL_DESCRIPTOR
: {
90 mach_msg_ool_descriptor_t
*dsc
;
93 * Destroy memory carried in the message
95 dsc
= &saddr
->out_of_line
;
96 if (dsc
->deallocate
) {
97 mach_msg_destroy_memory((vm_offset_t
)dsc
->address
,
103 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
105 mach_msg_ool_ports_descriptor_t
*dsc
;
106 mach_msg_type_number_t j
;
109 * Destroy port rights carried in the message
111 dsc
= &saddr
->ool_ports
;
112 ports
= (mach_port_t
*) dsc
->address
;
113 for (j
= 0; j
< dsc
->count
; j
++, ports
++) {
114 mach_msg_destroy_port(*ports
, dsc
->disposition
);
118 * Destroy memory carried in the message
120 if (dsc
->deallocate
) {
121 mach_msg_destroy_memory((vm_offset_t
)dsc
->address
,
122 dsc
->count
* sizeof(mach_port_t
));
132 mach_msg_destroy_port(mach_port_t port
, mach_msg_type_name_t type
)
134 if (MACH_PORT_VALID(port
)) switch (type
) {
135 case MACH_MSG_TYPE_MOVE_SEND
:
136 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
137 /* destroy the send/send-once right */
138 (void) mach_port_deallocate(mach_task_self(), port
);
141 case MACH_MSG_TYPE_MOVE_RECEIVE
:
142 /* destroy the receive right */
143 (void) mach_port_mod_refs(mach_task_self(), port
,
144 MACH_PORT_RIGHT_RECEIVE
, -1);
147 case MACH_MSG_TYPE_MAKE_SEND
:
148 /* create a send right and then destroy it */
149 (void) mach_port_insert_right(mach_task_self(), port
,
150 port
, MACH_MSG_TYPE_MAKE_SEND
);
151 (void) mach_port_deallocate(mach_task_self(), port
);
154 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
155 /* create a send-once right and then destroy it */
156 (void) mach_port_extract_right(mach_task_self(), port
,
157 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
159 (void) mach_port_deallocate(mach_task_self(), port
);
165 mach_msg_destroy_memory(vm_offset_t addr
, vm_size_t size
)
168 (void) vm_deallocate(mach_task_self(), addr
, size
);