Allow the kernel to be compile without KTRACE option.
[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_sopoll(struct socket *so, int events, struct ucred *cred)
367 {
368         int error;
369         struct netmsg_pru_sopoll msg;
370
371         netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
372                     0, netmsg_pru_sopoll);
373         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sopoll;
374         msg.nm_events = events;
375         msg.nm_cred = cred;
376         msg.nm_td = curthread;
377         error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
378         return (error);
379 }
380
381 int
382 so_pru_ctloutput(struct socket *so, struct sockopt *sopt)
383 {
384         struct netmsg_pru_ctloutput msg;
385         int error;
386
387         KKASSERT(!sopt->sopt_val || kva_p(sopt->sopt_val));
388         netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
389                     0, netmsg_pru_ctloutput);
390         /* TBD: move pr_ctloutput to pr_usrreqs */
391         msg.nm_prufn = so->so_proto->pr_ctloutput;
392         msg.nm_sopt = sopt;
393         error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
394         return (error);
395 }
396
397 /*
398  * Protocol control input, typically via icmp.
399  *
400  * If the protocol pr_ctlport is not NULL we call it to figure out the
401  * protocol port.  If NULL is returned we can just return, otherwise
402  * we issue a netmsg to call pr_ctlinput in the proper thread.
403  *
404  * This must be done synchronously as arg and/or extra may point to
405  * temporary data.
406  */
407 void
408 so_pru_ctlinput(struct protosw *pr, int cmd, struct sockaddr *arg, void *extra)
409 {
410         struct netmsg_pru_ctlinput msg;
411         lwkt_port_t port;
412
413         if (pr->pr_ctlport == NULL)
414                 return;
415         KKASSERT(pr->pr_ctlinput != NULL);
416         port = pr->pr_ctlport(cmd, arg, extra);
417         if (port == NULL)
418                 return;
419         netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
420                     0, netmsg_pru_ctlinput);
421         msg.nm_prufn = pr->pr_ctlinput;
422         msg.nm_cmd = cmd;
423         msg.nm_arg = arg;
424         msg.nm_extra = extra;
425         lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0);
426 }
427
428 /*
429  * If we convert all the protosw pr_ functions for all the protocols
430  * to take a message directly, this layer can go away.  For the moment
431  * our dispatcher ignores the return value, but since we are handling
432  * the replymsg ourselves we return EASYNC by convention.
433  */
434
435 /*
436  * Abort and destroy a socket.
437  */
438 void
439 netmsg_pru_abort(netmsg_t msg)
440 {
441         struct netmsg_pru_abort *nm = (void *)msg;
442         struct socket *so = msg->nm_so;
443         int error;
444
445         KKASSERT(so->so_state & SS_ABORTING);
446         so->so_state &= ~SS_ABORTING;
447         error = nm->nm_prufn(so);
448         if (error)
449                 sofree(so);
450         lwkt_replymsg(&msg->nm_lmsg, error);
451 }
452
453 #ifdef notused
454 void
455 netmsg_pru_accept(netmsg_t msg)
456 {
457         struct netmsg_pru_accept *nm = (void *)msg;
458
459         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
460 }
461 #endif
462
463 void
464 netmsg_pru_attach(netmsg_t msg)
465 {
466         struct netmsg_pru_attach *nm = (void *)msg;
467
468         lwkt_replymsg(&msg->nm_lmsg,
469                       nm->nm_prufn(msg->nm_so, nm->nm_proto, nm->nm_ai));
470 }
471
472 void
473 netmsg_pru_bind(netmsg_t msg)
474 {
475         struct netmsg_pru_bind *nm = (void *)msg;
476
477         lwkt_replymsg(&msg->nm_lmsg,
478                       nm->nm_prufn(msg->nm_so, nm->nm_nam, nm->nm_td));
479 }
480
481 void
482 netmsg_pru_connect(netmsg_t msg)
483 {
484         struct netmsg_pru_connect *nm = (void *)msg;
485
486         lwkt_replymsg(&msg->nm_lmsg,
487                       nm->nm_prufn(msg->nm_so, nm->nm_nam, nm->nm_td));
488 }
489
490 void
491 netmsg_pru_connect2(netmsg_t msg)
492 {
493         struct netmsg_pru_connect2 *nm = (void *)msg;
494
495         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so1, nm->nm_so2));
496 }
497
498 void
499 netmsg_pru_control(netmsg_t msg)
500 {
501         struct netmsg_pru_control *nm = (void *)msg;
502         int error;
503
504         error = nm->nm_prufn(msg->nm_so, nm->nm_cmd, nm->nm_data,
505                                 nm->nm_ifp, nm->nm_td);
506         lwkt_replymsg(&msg->nm_lmsg, error);
507 }
508
509 void
510 netmsg_pru_detach(netmsg_t msg)
511 {
512         struct netmsg_pru_detach *nm = (void *)msg;
513
514         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
515 }
516
517 void
518 netmsg_pru_disconnect(netmsg_t msg)
519 {
520         struct netmsg_pru_disconnect *nm = (void *)msg;
521
522         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
523 }
524
525 void
526 netmsg_pru_listen(netmsg_t msg)
527 {
528         struct netmsg_pru_listen *nm = (void *)msg;
529
530         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_td));
531 }
532
533 void
534 netmsg_pru_peeraddr(netmsg_t msg)
535 {
536         struct netmsg_pru_peeraddr *nm = (void *)msg;
537
538         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
539 }
540
541 void
542 netmsg_pru_rcvd(netmsg_t msg)
543 {
544         struct netmsg_pru_rcvd *nm = (void *)msg;
545
546         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_flags));
547 }
548
549 void
550 netmsg_pru_rcvoob(netmsg_t msg)
551 {
552         struct netmsg_pru_rcvoob *nm = (void *)msg;
553
554         lwkt_replymsg(&msg->nm_lmsg,
555                       nm->nm_prufn(msg->nm_so, nm->nm_m, nm->nm_flags));
556 }
557
558 void
559 netmsg_pru_send(netmsg_t msg)
560 {
561         struct netmsg_pru_send *nm = (void *)msg;
562         int error;
563
564         error = nm->nm_prufn(msg->nm_so, nm->nm_flags, nm->nm_m,
565                                 nm->nm_addr, nm->nm_control, nm->nm_td);
566         lwkt_replymsg(&msg->nm_lmsg, error);
567 }
568
569 void
570 netmsg_pru_sense(netmsg_t msg)
571 {
572         struct netmsg_pru_sense *nm = (void *)msg;
573
574         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_stat));
575 }
576
577 void
578 netmsg_pru_shutdown(netmsg_t msg)
579 {
580         struct netmsg_pru_shutdown *nm = (void *)msg;
581
582         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
583 }
584
585 void
586 netmsg_pru_sockaddr(netmsg_t msg)
587 {
588         struct netmsg_pru_sockaddr *nm = (void *)msg;
589
590         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
591 }
592
593 void
594 netmsg_pru_sopoll(netmsg_t msg)
595 {
596         struct netmsg_pru_sopoll *nm = (void *)msg;
597         int error;
598
599         error = nm->nm_prufn(msg->nm_so, nm->nm_events, nm->nm_cred, nm->nm_td);
600         lwkt_replymsg(&msg->nm_lmsg, error);
601 }
602
603 void
604 netmsg_pru_ctloutput(netmsg_t msg)
605 {
606         struct netmsg_pru_ctloutput *nm = (void *)msg;
607
608         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_sopt));
609 }
610
611 void
612 netmsg_pru_ctlinput(netmsg_t msg)
613 {
614         struct netmsg_pru_ctlinput *nm = (void *)msg;
615
616         nm->nm_prufn(nm->nm_cmd, nm->nm_arg, nm->nm_extra);
617         lwkt_replymsg(&nm->nm_netmsg.nm_lmsg, 0);
618 }
619
620 void
621 netmsg_pr_timeout(netmsg_t msg)
622 {
623         struct netmsg_pr_timeout *nm = (void *)msg;
624
625         lwkt_replymsg(&msg->nm_lmsg, nm->nm_prfn());
626 }
627
628 /*
629  * Handle a predicate event request.  This function is only called once
630  * when the predicate message queueing request is received.
631  */
632 void
633 netmsg_so_notify(netmsg_t netmsg)
634 {
635         struct netmsg_so_notify *msg = (void *)netmsg;
636         struct signalsockbuf *ssb;
637
638         ssb = (msg->nm_etype & NM_REVENT) ?
639                         &msg->nm_so->so_rcv :
640                         &msg->nm_so->so_snd;
641
642         /*
643          * Reply immediately if the event has occured, otherwise queue the
644          * request.
645          */
646         if (msg->nm_predicate(&msg->nm_netmsg)) {
647                 lwkt_replymsg(&msg->nm_netmsg.nm_lmsg,
648                               msg->nm_netmsg.nm_lmsg.ms_error);
649         } else {
650                 TAILQ_INSERT_TAIL(&ssb->ssb_sel.si_mlist, msg, nm_list);
651                 ssb->ssb_flags |= SSB_MEVENT;
652         }
653 }
654
655 /*
656  * Called by doio when trying to abort a netmsg_so_notify message.
657  * Unlike the other functions this one is dispatched directly by
658  * the LWKT subsystem, so it takes a lwkt_msg_t as an argument.
659  *
660  * The original message, lmsg, is under the control of the caller and
661  * will not be destroyed until we return so we can safely reference it
662  * in our synchronous abort request.
663  *
664  * This part of the abort request occurs on the originating cpu which
665  * means we may race the message flags and the original message may
666  * not even have been processed by the target cpu yet.
667  */
668 void
669 netmsg_so_notify_doabort(lwkt_msg_t lmsg)
670 {
671         struct netmsg_so_notify_abort msg;
672
673         if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
674                 netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
675                             0, netmsg_so_notify_abort);
676                 msg.nm_notifymsg = (void *)lmsg;
677                 lwkt_domsg(lmsg->ms_target_port, &msg.nm_netmsg.nm_lmsg, 0);
678         }
679 }
680
681 /*
682  * Predicate requests can be aborted.  This function is only called once
683  * and will interlock against processing/reply races (since such races
684  * occur on the same thread that controls the port where the abort is 
685  * requeued).
686  *
687  * This part of the abort request occurs on the target cpu.  The message
688  * flags must be tested again in case the test that we did on the
689  * originating cpu raced.  Since messages are handled in sequence, the
690  * original message will have already been handled by the loop and either
691  * replied to or queued.
692  *
693  * We really only need to interlock with MSGF_REPLY (a bit that is set on
694  * our cpu when we reply).  Note that MSGF_DONE is not set until the
695  * reply reaches the originating cpu.  Test both bits anyway.
696  */
697 void
698 netmsg_so_notify_abort(netmsg_t netmsg)
699 {
700         struct netmsg_so_notify_abort *abrtmsg = (void *)netmsg;
701         struct netmsg_so_notify *msg = abrtmsg->nm_notifymsg;
702         struct signalsockbuf *ssb;
703
704         /*
705          * The original notify message is not destroyed until after the
706          * abort request is returned, so we can check its state.
707          */
708         if ((msg->nm_netmsg.nm_lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
709                 ssb = (msg->nm_etype & NM_REVENT) ?
710                                 &msg->nm_so->so_rcv :
711                                 &msg->nm_so->so_snd;
712                 TAILQ_REMOVE(&ssb->ssb_sel.si_mlist, msg, nm_list);
713                 lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, EINTR);
714         }
715
716         /*
717          * Reply to the abort message
718          */
719         lwkt_replymsg(&abrtmsg->nm_netmsg.nm_lmsg, 0);
720 }
721