kernel - Tear out socket polling
[dragonfly.git] / sys / kern / uipc_msg.c
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                 TAILQ_INSERT_TAIL(&ssb->ssb_sel.si_mlist, msg, nm_list);
625                 ssb->ssb_flags |= SSB_MEVENT;
626         }
627 }
628
629 /*
630  * Called by doio when trying to abort a netmsg_so_notify message.
631  * Unlike the other functions this one is dispatched directly by
632  * the LWKT subsystem, so it takes a lwkt_msg_t as an argument.
633  *
634  * The original message, lmsg, is under the control of the caller and
635  * will not be destroyed until we return so we can safely reference it
636  * in our synchronous abort request.
637  *
638  * This part of the abort request occurs on the originating cpu which
639  * means we may race the message flags and the original message may
640  * not even have been processed by the target cpu yet.
641  */
642 void
643 netmsg_so_notify_doabort(lwkt_msg_t lmsg)
644 {
645         struct netmsg_so_notify_abort msg;
646
647         if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
648                 netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
649                             0, netmsg_so_notify_abort);
650                 msg.nm_notifymsg = (void *)lmsg;
651                 lwkt_domsg(lmsg->ms_target_port, &msg.nm_netmsg.nm_lmsg, 0);
652         }
653 }
654
655 /*
656  * Predicate requests can be aborted.  This function is only called once
657  * and will interlock against processing/reply races (since such races
658  * occur on the same thread that controls the port where the abort is 
659  * requeued).
660  *
661  * This part of the abort request occurs on the target cpu.  The message
662  * flags must be tested again in case the test that we did on the
663  * originating cpu raced.  Since messages are handled in sequence, the
664  * original message will have already been handled by the loop and either
665  * replied to or queued.
666  *
667  * We really only need to interlock with MSGF_REPLY (a bit that is set on
668  * our cpu when we reply).  Note that MSGF_DONE is not set until the
669  * reply reaches the originating cpu.  Test both bits anyway.
670  */
671 void
672 netmsg_so_notify_abort(netmsg_t netmsg)
673 {
674         struct netmsg_so_notify_abort *abrtmsg = (void *)netmsg;
675         struct netmsg_so_notify *msg = abrtmsg->nm_notifymsg;
676         struct signalsockbuf *ssb;
677
678         /*
679          * The original notify message is not destroyed until after the
680          * abort request is returned, so we can check its state.
681          */
682         if ((msg->nm_netmsg.nm_lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
683                 ssb = (msg->nm_etype & NM_REVENT) ?
684                                 &msg->nm_so->so_rcv :
685                                 &msg->nm_so->so_snd;
686                 TAILQ_REMOVE(&ssb->ssb_sel.si_mlist, msg, nm_list);
687                 lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, EINTR);
688         }
689
690         /*
691          * Reply to the abort message
692          */
693         lwkt_replymsg(&abrtmsg->nm_netmsg.nm_lmsg, 0);
694 }
695