1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: ipc_deadname.c,v $
29 * Revision 2.2 93/01/14 17:53:31 danner
30 * 64bit cleanup.
31 * [92/12/01 af]
32 *
33 * Created.
34 * [92/05/25 dlb]
35 *
36 * Revision 2.1 92/05/27 01:00:30 jeffreyh
37 * Created.
38 *
39 */
40
41 #include <ipc/ipc_port.h>
42 #include <mach/kern_return.h>
43 #include <norma/ipc_node.h>
44 #include <kern/host.h>
45
46 extern ipc_port_t norma_port_lookup();
47 /*
48 * File: norma/ipc_dnrequest.c
49 * Author: David L. Black
50 * Date: 1992
51 *
52 * Functions for managing NORMA IPC dead name requests.
53 */
54
55 /*
56 * Dead name notifications have a two-level structure: NORMA
57 * code tracks which nodes have to be notified, and the proxy
58 * structures on those nodes track the actual notifications.
59 * The existence of a dead name notification causes destruction
60 * of the corresponding proxies to be eagerly evaluated. A special
61 * value for the notify port is used to redirect dead name
62 * notifications for remote proxies into the norma system.
63 */
64
65 /*
66 * norma_ipc_dnrequest_init:
67 *
68 * Called by the ipc system the first time a dead name request
69 * is queued for a port. If the port is a proxy, ask the principal
70 * to tell us when it dies.
71 */
72
73 void
74 norma_ipc_dnrequest_init(port)
75 ipc_port_t port;
76 {
77 kern_return_t result;
78
79 if (!IP_NORMA_IS_PROXY(port))
80 return;
81
82 result = r_norma_ipc_node_dnrequest(
83 remote_host_priv(port->ip_norma_dest_node),
84 port->ip_norma_uid, node_self());
85
86 if (result != KERN_SUCCESS) {
87 /*
88 * Principal is already dead, so kill this proxy.
89 * Caller will discover port is dead when it
90 * rechecks after return from ipc_port_dngrow();
91 */
92 norma_ipc_dead_destination(port);
93 }
94 }
95
96 /*
97 * norma_ipc_node_dnrequest:
98 *
99 * Called on principal's node by a proxy that wants to be
100 * notified when the receive right dies (so that it can process
101 * its dead name requests). Queue a norma fake dead name notification
102 * so that we get called at that time.
103 */
104
105 kern_return_t
106 norma_ipc_node_dnrequest(host_priv, uid, node)
107 host_t host_priv;
108 natural_t uid;
109 natural_t node;
110 {
111 ipc_port_t port;
112 ipc_port_request_index_t junk_request;
113 kern_return_t kr;
114
115 if (host_priv == HOST_NULL)
116 return(KERN_INVALID_ARGUMENT);
117
118 port = norma_port_lookup(uid);
119
120 if ((port == IP_NULL) || !ip_active(port)) {
121 /*
122 * The receive right is already dead.
123 */
124 printf("Stale dn request node %d uid %d\n");
125 r_norma_ipc_node_dnnotify(remote_host_priv(node), uid);
126 return(KERN_SUCCESS);
127 }
128
129 if (port->ip_norma_is_proxy) {
130 /*
131 * Send this along to the principal. This is an
132 * asynchronous message.
133 */
134 r_norma_ipc_node_dnrequest(
135 remote_host_priv(port->ip_norma_dest_node),
136 uid, node);
137 return(KERN_SUCCESS);
138 }
139
140 /*
141 * Place norma dnrequest.
142 */
143 kr = ipc_port_dnrequest(port, NODE_TO_DNREQUEST_NAME(node),
144 IP_NORMA_FAKE_DNREQUEST,
145 &junk_request);
146 while (kr != KERN_SUCCESS) {
147 kr = ipc_port_dngrow(port);
148 if (kr != KERN_SUCCESS)
149 panic("norma_ipc_node_dnrequest: ipc_port_dngrow failure");
150
151 kr = ipc_port_dnrequest(port, NODE_TO_DNREQUEST_NAME(node),
152 IP_NORMA_FAKE_DNREQUEST,
153 &junk_request);
154 }
155
156 return(KERN_SUCCESS);
157 }
158
159 /*
160 * norma_ipc_notify_dead_name:
161 *
162 * The receive right for a port has died and the proxy on some node
163 * wants to know about it. Tell it.
164 *
165 * NOTE: This routine depends on norma_ipc_port_destroy NOT clobbering
166 * the port's uid.
167 */
168
169 void
170 norma_ipc_notify_dead_name(port, name)
171 ipc_port_t port;
172 natural_t name;
173 {
174 assert(!IP_NORMA_IS_PROXY(port));
175
176 r_norma_ipc_node_dnnotify(
177 remote_host_priv(DNREQUEST_NAME_TO_NODE(name)),
178 port->ip_norma_uid);
179 }
180
181 /*
182 * norma_ipc_node_dnnotify:
183 *
184 * Called on proxy node when principal has died. Kill proxy to
185 * trigger its dead name notifications. Proxy may already be
186 * gone for other reasons, so just ignore this if we can't find one.
187 */
188
189 void
190 norma_ipc_node_dnnotify(host_priv, uid)
191 host_t host_priv;
192 natural_t uid;
193 {
194 ipc_port_t port;
195
196 port = norma_port_lookup(uid);
197
198 assert(port == IP_NULL || IP_NORMA_IS_PROXY(port));
199
200 /*
201 * Ignore this if we can't find the proxy. If the
202 * port is queued, the send will fail and destroy the
203 * proxy anyway; destroying it prematurely will just
204 * confuse the send logic.
205 */
206 if ((port != IP_NULL) && !netipc_port_is_queued(port))
207 norma_ipc_dead_destination(port);
208 }
Cache object: e1d8b2ea55e62b5daed8aff5ce9128ff
|