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