xref: /dflybsd-src/sys/kern/uipc_msg.c (revision a9656fbcd49c376aba5e04370d8b0f1fa96e063c)
1 /*
2  * Copyright (c) 2003, 2004 Jeffrey M. Hsu.  All rights reserved.
3  * Copyright (c) 2003, 2004 The DragonFly Project.  All rights reserved.
4  *
5  * This code is derived from software contributed to The DragonFly Project
6  * by Jeffrey M. Hsu.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of The DragonFly Project nor the names of its
17  *    contributors may be used to endorse or promote products derived
18  *    from this software without specific, prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $DragonFly: src/sys/kern/uipc_msg.c,v 1.26 2008/10/27 02:56:30 sephe Exp $
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/msgport.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/socketops.h>
44 #include <sys/thread.h>
45 #include <sys/thread2.h>
46 #include <sys/msgport2.h>
47 #include <vm/pmap.h>
48 #include <net/netmsg2.h>
49 
50 #include <net/netisr.h>
51 #include <net/netmsg.h>
52 
53 /*
54  * Abort a socket and free it.  Called from soabort() only.
55  *
56  * The SS_ABORTING flag must already be set.
57  */
58 void
59 so_pru_abort(struct socket *so)
60 {
61 	struct netmsg_pru_abort msg;
62 
63 	KKASSERT(so->so_state & SS_ABORTING);
64 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
65 		    0, netmsg_pru_abort);
66 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
67 	(void)lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
68 }
69 
70 /*
71  * Abort a socket and free it, asynchronously.  Called from
72  * soaborta() only.
73  *
74  * The SS_ABORTING flag must already be set.
75  */
76 void
77 so_pru_aborta(struct socket *so)
78 {
79 	struct netmsg_pru_abort *msg;
80 
81 	KKASSERT(so->so_state & SS_ABORTING);
82 	msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO);
83 	netmsg_init(&msg->nm_netmsg, so, &netisr_afree_rport,
84 		    0, netmsg_pru_abort);
85 	msg->nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
86 	lwkt_sendmsg(so->so_port, &msg->nm_netmsg.nm_lmsg);
87 }
88 
89 /*
90  * Abort a socket and free it.  Called from soabort_oncpu() only.
91  * Caller must make sure that the current CPU is inpcb's owner CPU.
92  *
93  * The SS_ABORTING flag must already be set.
94  */
95 void
96 so_pru_abort_oncpu(struct socket *so)
97 {
98 	so->so_proto->pr_usrreqs->pru_abort(so);
99 }
100 
101 int
102 so_pru_accept(struct socket *so, struct sockaddr **nam)
103 {
104 	/* Block (memory allocation) in process context. XXX JH */
105 	return ((*so->so_proto->pr_usrreqs->pru_accept)(so, nam));
106 
107 #ifdef notdef
108 	int error;
109 	struct netmsg_pru_accept msg;
110 
111 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
112 		    0, netmsg_pru_accept);
113 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_accept;
114 	msg.nm_nam = nam;
115 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
116 	return (error);
117 #endif
118 }
119 
120 int
121 so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai)
122 {
123 	int error;
124 	struct netmsg_pru_attach msg;
125 
126 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
127 		    0, netmsg_pru_attach);
128 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_attach;
129 	msg.nm_proto = proto;
130 	msg.nm_ai = ai;
131 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
132 	return (error);
133 }
134 
135 /*
136  * NOTE: If the target port changes the bind operation will deal with it.
137  */
138 int
139 so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
140 {
141 	int error;
142 	struct netmsg_pru_bind msg;
143 
144 #if 0
145 	port = so->so_proto->pr_mport(NULL, nam, NULL);
146 #endif
147 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
148 		    0, netmsg_pru_bind);
149 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_bind;
150 	msg.nm_nam = nam;
151 	msg.nm_td = td;		/* used only for prison_ip() XXX JH */
152 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
153 	return (error);
154 }
155 
156 int
157 so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
158 {
159 	int error;
160 	struct netmsg_pru_connect msg;
161 
162 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
163 		    0, netmsg_pru_connect);
164 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_connect;
165 	msg.nm_nam = nam;
166 	msg.nm_td = td;
167 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
168 	return (error);
169 }
170 
171 int
172 so_pru_connect2(struct socket *so1, struct socket *so2)
173 {
174 	int error;
175 	struct netmsg_pru_connect2 msg;
176 
177 	netmsg_init(&msg.nm_netmsg, so1, &curthread->td_msgport,
178 		    0, netmsg_pru_connect2);
179 	msg.nm_prufn = so1->so_proto->pr_usrreqs->pru_connect2;
180 	msg.nm_so1 = so1;
181 	msg.nm_so2 = so2;
182 	error = lwkt_domsg(so1->so_port, &msg.nm_netmsg.nm_lmsg, 0);
183 	return (error);
184 }
185 
186 int
187 so_pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
188 {
189 	return ((*so->so_proto->pr_usrreqs->pru_control)(
190 			so, cmd, data, ifp, curthread));
191 #ifdef gag	/* does copyin and copyout deep inside stack XXX JH */
192 	int error;
193 	struct netmsg_pru_control msg;
194 
195 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
196 		    0, netmsg_pru_control);
197 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_control;
198 	msg.nm_cmd = cmd;
199 	msg.nm_data = data;
200 	msg.nm_ifp = ifp;
201 	msg.nm_td = td;
202 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
203 	return (error);
204 #endif
205 }
206 
207 int
208 so_pru_detach(struct socket *so)
209 {
210 	int error;
211 	struct netmsg_pru_detach msg;
212 
213 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
214 		    0, netmsg_pru_detach);
215 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_detach;
216 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
217 	return (error);
218 }
219 
220 int
221 so_pru_disconnect(struct socket *so)
222 {
223 	int error;
224 	struct netmsg_pru_disconnect msg;
225 
226 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
227 		    0, netmsg_pru_disconnect);
228 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_disconnect;
229 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
230 	return (error);
231 }
232 
233 int
234 so_pru_listen(struct socket *so, struct thread *td)
235 {
236 	int error;
237 	struct netmsg_pru_listen msg;
238 
239 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
240 		    0, netmsg_pru_listen);
241 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_listen;
242 	msg.nm_td = td;		/* used only for prison_ip() XXX JH */
243 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
244 	return (error);
245 }
246 
247 int
248 so_pru_peeraddr(struct socket *so, struct sockaddr **nam)
249 {
250 	int error;
251 	struct netmsg_pru_peeraddr msg;
252 
253 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
254 		    0, netmsg_pru_peeraddr);
255 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_peeraddr;
256 	msg.nm_nam = nam;
257 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
258 	return (error);
259 }
260 
261 int
262 so_pru_rcvd(struct socket *so, int flags)
263 {
264 	int error;
265 	struct netmsg_pru_rcvd msg;
266 
267 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
268 		    0, netmsg_pru_rcvd);
269 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvd;
270 	msg.nm_flags = flags;
271 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
272 	return (error);
273 }
274 
275 int
276 so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags)
277 {
278 	int error;
279 	struct netmsg_pru_rcvoob msg;
280 
281 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
282 		    0, netmsg_pru_rcvoob);
283 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvoob;
284 	msg.nm_m = m;
285 	msg.nm_flags = flags;
286 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
287 	return (error);
288 }
289 
290 /*
291  * NOTE: so_pru_send() is the only code which uses pr_mport() now.
292  *
293  * NOTE: If the target port changes the implied connect will deal with it.
294  */
295 int
296 so_pru_send(struct socket *so, int flags, struct mbuf *m,
297 	    struct sockaddr *addr, struct mbuf *control, struct thread *td)
298 {
299 	int error;
300 	struct netmsg_pru_send msg;
301 	lwkt_port_t port;
302 
303 	port = so->so_proto->pr_mport(so, addr, &m);
304 	if (port == NULL) {
305 		KKASSERT(m == NULL);
306 		return EINVAL;
307 	}
308 
309 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
310 		    0, netmsg_pru_send);
311 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_send;
312 	msg.nm_flags = flags;
313 	msg.nm_m = m;
314 	msg.nm_addr = addr;
315 	msg.nm_control = control;
316 	msg.nm_td = td;
317 	error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0);
318 	return (error);
319 }
320 
321 /*
322  * MPSAFE
323  */
324 int
325 so_pru_sense(struct socket *so, struct stat *sb)
326 {
327 	int error;
328 	struct netmsg_pru_sense msg;
329 
330 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
331 		    0, netmsg_pru_sense);
332 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sense;
333 	msg.nm_stat = sb;
334 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
335 	return (error);
336 }
337 
338 int
339 so_pru_shutdown(struct socket *so)
340 {
341 	int error;
342 	struct netmsg_pru_shutdown msg;
343 
344 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
345 		    0, netmsg_pru_shutdown);
346 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_shutdown;
347 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
348 	return (error);
349 }
350 
351 int
352 so_pru_sockaddr(struct socket *so, struct sockaddr **nam)
353 {
354 	int error;
355 	struct netmsg_pru_sockaddr msg;
356 
357 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
358 		    0, netmsg_pru_sockaddr);
359 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sockaddr;
360 	msg.nm_nam = nam;
361 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
362 	return (error);
363 }
364 
365 int
366 so_pru_ctloutput(struct socket *so, struct sockopt *sopt)
367 {
368 	struct netmsg_pru_ctloutput msg;
369 	int error;
370 
371 	KKASSERT(!sopt->sopt_val || kva_p(sopt->sopt_val));
372 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
373 		    0, netmsg_pru_ctloutput);
374 	/* TBD: move pr_ctloutput to pr_usrreqs */
375 	msg.nm_prufn = so->so_proto->pr_ctloutput;
376 	msg.nm_sopt = sopt;
377 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
378 	return (error);
379 }
380 
381 /*
382  * Protocol control input, typically via icmp.
383  *
384  * If the protocol pr_ctlport is not NULL we call it to figure out the
385  * protocol port.  If NULL is returned we can just return, otherwise
386  * we issue a netmsg to call pr_ctlinput in the proper thread.
387  *
388  * This must be done synchronously as arg and/or extra may point to
389  * temporary data.
390  */
391 void
392 so_pru_ctlinput(struct protosw *pr, int cmd, struct sockaddr *arg, void *extra)
393 {
394 	struct netmsg_pru_ctlinput msg;
395 	lwkt_port_t port;
396 
397 	if (pr->pr_ctlport == NULL)
398 		return;
399 	KKASSERT(pr->pr_ctlinput != NULL);
400 	port = pr->pr_ctlport(cmd, arg, extra);
401 	if (port == NULL)
402 		return;
403 	netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
404 		    0, netmsg_pru_ctlinput);
405 	msg.nm_prufn = pr->pr_ctlinput;
406 	msg.nm_cmd = cmd;
407 	msg.nm_arg = arg;
408 	msg.nm_extra = extra;
409 	lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0);
410 }
411 
412 /*
413  * If we convert all the protosw pr_ functions for all the protocols
414  * to take a message directly, this layer can go away.  For the moment
415  * our dispatcher ignores the return value, but since we are handling
416  * the replymsg ourselves we return EASYNC by convention.
417  */
418 
419 /*
420  * Abort and destroy a socket.
421  */
422 void
423 netmsg_pru_abort(netmsg_t msg)
424 {
425 	struct netmsg_pru_abort *nm = (void *)msg;
426 	struct socket *so = msg->nm_so;
427 	int error;
428 
429 	KKASSERT(so->so_state & SS_ABORTING);
430 	so->so_state &= ~SS_ABORTING;
431 	error = nm->nm_prufn(so);
432 	if (error)
433 		sofree(so);
434 	lwkt_replymsg(&msg->nm_lmsg, error);
435 }
436 
437 #ifdef notused
438 void
439 netmsg_pru_accept(netmsg_t msg)
440 {
441 	struct netmsg_pru_accept *nm = (void *)msg;
442 
443 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
444 }
445 #endif
446 
447 void
448 netmsg_pru_attach(netmsg_t msg)
449 {
450 	struct netmsg_pru_attach *nm = (void *)msg;
451 
452 	lwkt_replymsg(&msg->nm_lmsg,
453 		      nm->nm_prufn(msg->nm_so, nm->nm_proto, nm->nm_ai));
454 }
455 
456 void
457 netmsg_pru_bind(netmsg_t msg)
458 {
459 	struct netmsg_pru_bind *nm = (void *)msg;
460 
461 	lwkt_replymsg(&msg->nm_lmsg,
462 		      nm->nm_prufn(msg->nm_so, nm->nm_nam, nm->nm_td));
463 }
464 
465 void
466 netmsg_pru_connect(netmsg_t msg)
467 {
468 	struct netmsg_pru_connect *nm = (void *)msg;
469 
470 	lwkt_replymsg(&msg->nm_lmsg,
471 		      nm->nm_prufn(msg->nm_so, nm->nm_nam, nm->nm_td));
472 }
473 
474 void
475 netmsg_pru_connect2(netmsg_t msg)
476 {
477 	struct netmsg_pru_connect2 *nm = (void *)msg;
478 
479 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so1, nm->nm_so2));
480 }
481 
482 void
483 netmsg_pru_control(netmsg_t msg)
484 {
485 	struct netmsg_pru_control *nm = (void *)msg;
486 	int error;
487 
488 	error = nm->nm_prufn(msg->nm_so, nm->nm_cmd, nm->nm_data,
489 				nm->nm_ifp, nm->nm_td);
490 	lwkt_replymsg(&msg->nm_lmsg, error);
491 }
492 
493 void
494 netmsg_pru_detach(netmsg_t msg)
495 {
496 	struct netmsg_pru_detach *nm = (void *)msg;
497 
498 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
499 }
500 
501 void
502 netmsg_pru_disconnect(netmsg_t msg)
503 {
504 	struct netmsg_pru_disconnect *nm = (void *)msg;
505 
506 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
507 }
508 
509 void
510 netmsg_pru_listen(netmsg_t msg)
511 {
512 	struct netmsg_pru_listen *nm = (void *)msg;
513 
514 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_td));
515 }
516 
517 void
518 netmsg_pru_peeraddr(netmsg_t msg)
519 {
520 	struct netmsg_pru_peeraddr *nm = (void *)msg;
521 
522 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
523 }
524 
525 void
526 netmsg_pru_rcvd(netmsg_t msg)
527 {
528 	struct netmsg_pru_rcvd *nm = (void *)msg;
529 
530 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_flags));
531 }
532 
533 void
534 netmsg_pru_rcvoob(netmsg_t msg)
535 {
536 	struct netmsg_pru_rcvoob *nm = (void *)msg;
537 
538 	lwkt_replymsg(&msg->nm_lmsg,
539 		      nm->nm_prufn(msg->nm_so, nm->nm_m, nm->nm_flags));
540 }
541 
542 void
543 netmsg_pru_send(netmsg_t msg)
544 {
545 	struct netmsg_pru_send *nm = (void *)msg;
546 	int error;
547 
548 	error = nm->nm_prufn(msg->nm_so, nm->nm_flags, nm->nm_m,
549 				nm->nm_addr, nm->nm_control, nm->nm_td);
550 	lwkt_replymsg(&msg->nm_lmsg, error);
551 }
552 
553 void
554 netmsg_pru_sense(netmsg_t msg)
555 {
556 	struct netmsg_pru_sense *nm = (void *)msg;
557 
558 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_stat));
559 }
560 
561 void
562 netmsg_pru_shutdown(netmsg_t msg)
563 {
564 	struct netmsg_pru_shutdown *nm = (void *)msg;
565 
566 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
567 }
568 
569 void
570 netmsg_pru_sockaddr(netmsg_t msg)
571 {
572 	struct netmsg_pru_sockaddr *nm = (void *)msg;
573 
574 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
575 }
576 
577 void
578 netmsg_pru_ctloutput(netmsg_t msg)
579 {
580 	struct netmsg_pru_ctloutput *nm = (void *)msg;
581 
582 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_sopt));
583 }
584 
585 void
586 netmsg_pru_ctlinput(netmsg_t msg)
587 {
588 	struct netmsg_pru_ctlinput *nm = (void *)msg;
589 
590 	nm->nm_prufn(nm->nm_cmd, nm->nm_arg, nm->nm_extra);
591 	lwkt_replymsg(&nm->nm_netmsg.nm_lmsg, 0);
592 }
593 
594 void
595 netmsg_pr_timeout(netmsg_t msg)
596 {
597 	struct netmsg_pr_timeout *nm = (void *)msg;
598 
599 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prfn());
600 }
601 
602 /*
603  * Handle a predicate event request.  This function is only called once
604  * when the predicate message queueing request is received.
605  */
606 void
607 netmsg_so_notify(netmsg_t netmsg)
608 {
609 	struct netmsg_so_notify *msg = (void *)netmsg;
610 	struct signalsockbuf *ssb;
611 
612 	ssb = (msg->nm_etype & NM_REVENT) ?
613 			&msg->nm_so->so_rcv :
614 			&msg->nm_so->so_snd;
615 
616 	/*
617 	 * Reply immediately if the event has occured, otherwise queue the
618 	 * request.
619 	 */
620 	if (msg->nm_predicate(&msg->nm_netmsg)) {
621 		lwkt_replymsg(&msg->nm_netmsg.nm_lmsg,
622 			      msg->nm_netmsg.nm_lmsg.ms_error);
623 	} else {
624 		lwkt_gettoken(&kq_token);
625 		TAILQ_INSERT_TAIL(&ssb->ssb_kq.ki_mlist, msg, nm_list);
626 		lwkt_reltoken(&kq_token);
627 		ssb->ssb_flags |= SSB_MEVENT;
628 	}
629 }
630 
631 /*
632  * Called by doio when trying to abort a netmsg_so_notify message.
633  * Unlike the other functions this one is dispatched directly by
634  * the LWKT subsystem, so it takes a lwkt_msg_t as an argument.
635  *
636  * The original message, lmsg, is under the control of the caller and
637  * will not be destroyed until we return so we can safely reference it
638  * in our synchronous abort request.
639  *
640  * This part of the abort request occurs on the originating cpu which
641  * means we may race the message flags and the original message may
642  * not even have been processed by the target cpu yet.
643  */
644 void
645 netmsg_so_notify_doabort(lwkt_msg_t lmsg)
646 {
647 	struct netmsg_so_notify_abort msg;
648 
649 	if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
650 		netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
651 			    0, netmsg_so_notify_abort);
652 		msg.nm_notifymsg = (void *)lmsg;
653 		lwkt_domsg(lmsg->ms_target_port, &msg.nm_netmsg.nm_lmsg, 0);
654 	}
655 }
656 
657 /*
658  * Predicate requests can be aborted.  This function is only called once
659  * and will interlock against processing/reply races (since such races
660  * occur on the same thread that controls the port where the abort is
661  * requeued).
662  *
663  * This part of the abort request occurs on the target cpu.  The message
664  * flags must be tested again in case the test that we did on the
665  * originating cpu raced.  Since messages are handled in sequence, the
666  * original message will have already been handled by the loop and either
667  * replied to or queued.
668  *
669  * We really only need to interlock with MSGF_REPLY (a bit that is set on
670  * our cpu when we reply).  Note that MSGF_DONE is not set until the
671  * reply reaches the originating cpu.  Test both bits anyway.
672  */
673 void
674 netmsg_so_notify_abort(netmsg_t netmsg)
675 {
676 	struct netmsg_so_notify_abort *abrtmsg = (void *)netmsg;
677 	struct netmsg_so_notify *msg = abrtmsg->nm_notifymsg;
678 	struct signalsockbuf *ssb;
679 
680 	/*
681 	 * The original notify message is not destroyed until after the
682 	 * abort request is returned, so we can check its state.
683 	 */
684 	if ((msg->nm_netmsg.nm_lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
685 		ssb = (msg->nm_etype & NM_REVENT) ?
686 				&msg->nm_so->so_rcv :
687 				&msg->nm_so->so_snd;
688 		lwkt_gettoken(&kq_token);
689 		TAILQ_REMOVE(&ssb->ssb_kq.ki_mlist, msg, nm_list);
690 		lwkt_reltoken(&kq_token);
691 		lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, EINTR);
692 	}
693 
694 	/*
695 	 * Reply to the abort message
696 	 */
697 	lwkt_replymsg(&abrtmsg->nm_netmsg.nm_lmsg, 0);
698 }
699 
700