When a kernel-created thread exits, properly remove it from gd_tdallq and
[dragonfly.git] / sys / kern / uipc_msg.c
1 /*
2  * Copyright (c) 2003, 2004 Jeffrey Hsu.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Jeffrey M. Hsu.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  * 
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $DragonFly: src/sys/kern/uipc_msg.c,v 1.12 2004/06/07 07:01:34 dillon Exp $
31  */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/msgport.h>
36 #include <sys/protosw.h>
37 #include <sys/socket.h>
38 #include <sys/socketvar.h>
39 #include <sys/socketops.h>
40 #include <sys/thread.h>
41 #include <sys/thread2.h>
42 #include <sys/msgport2.h>
43
44 #include <net/netisr.h>
45 #include <net/netmsg.h>
46
47 int
48 so_pru_abort(struct socket *so)
49 {
50         int error;
51         struct netmsg_pru_abort msg;
52         lwkt_port_t port;
53
54         port = so->so_proto->pr_mport(so, NULL, PRU_ABORT);
55         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
56                 lwkt_cmd_func(netmsg_pru_abort), lwkt_cmd_op_none);
57         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
58         msg.nm_so = so;
59         error = lwkt_domsg(port, &msg.nm_lmsg);
60         return (error);
61 }
62
63 int
64 so_pru_accept(struct socket *so, struct sockaddr **nam)
65 {
66         /* Block (memory allocation) in process context. XXX JH */
67         return ((*so->so_proto->pr_usrreqs->pru_accept)(so, nam));
68
69 #ifdef notdef
70         int error;
71         struct netmsg_pru_accept msg;
72         lwkt_port_t port;
73
74         port = so->so_proto->pr_mport(so, NULL, PRU_ACCEPT);
75         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
76                 lwkt_cmd_func(netmsg_pru_accept), lwkt_cmd_op_none);
77         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_accept;
78         msg.nm_so = so;
79         msg.nm_nam = nam;
80         error = lwkt_domsg(port, &msg.nm_lmsg);
81         return (error);
82 #endif
83 }
84
85 int
86 so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai)
87 {
88         int error;
89         struct netmsg_pru_attach msg;
90         lwkt_port_t port;
91
92         port = so->so_proto->pr_mport(NULL, NULL, PRU_ATTACH);
93         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
94                 lwkt_cmd_func(netmsg_pru_attach), lwkt_cmd_op_none);
95         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_attach;
96         msg.nm_so = so;
97         msg.nm_proto = proto;
98         msg.nm_ai = ai;
99         error = lwkt_domsg(port, &msg.nm_lmsg);
100         return (error);
101 }
102
103 int
104 so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
105 {
106         int error;
107         struct netmsg_pru_bind msg;
108         lwkt_port_t port;
109
110         /* Send mesg to thread for new address. */
111         port = so->so_proto->pr_mport(NULL, nam, PRU_BIND);
112         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
113                 lwkt_cmd_func(netmsg_pru_bind), lwkt_cmd_op_none);
114         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_bind;
115         msg.nm_so = so;
116         msg.nm_nam = nam;
117         msg.nm_td = td;         /* used only for prison_ip() XXX JH */
118         error = lwkt_domsg(port, &msg.nm_lmsg);
119         return (error);
120 }
121
122 int
123 so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
124 {
125         int error;
126         struct netmsg_pru_connect msg;
127         lwkt_port_t port;
128
129         port = so->so_proto->pr_mport(so, nam, PRU_CONNECT);
130         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
131                 lwkt_cmd_func(netmsg_pru_connect), lwkt_cmd_op_none);
132         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_connect;
133         msg.nm_so = so;
134         msg.nm_nam = nam;
135         msg.nm_td = td;
136         error = lwkt_domsg(port, &msg.nm_lmsg);
137         return (error);
138 }
139
140 int
141 so_pru_connect2(struct socket *so1, struct socket *so2)
142 {
143         int error;
144         struct netmsg_pru_connect2 msg;
145         lwkt_port_t port;
146
147         port = so1->so_proto->pr_mport(so1, NULL, PRU_CONNECT2);
148         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
149                 lwkt_cmd_func(netmsg_pru_connect2), lwkt_cmd_op_none);
150         msg.nm_prufn = so1->so_proto->pr_usrreqs->pru_connect2;
151         msg.nm_so1 = so1;
152         msg.nm_so2 = so2;
153         error = lwkt_domsg(port, &msg.nm_lmsg);
154         return (error);
155 }
156
157 int
158 so_pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
159     struct thread *td)
160 {
161         return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, ifp,
162             td));
163 #ifdef gag      /* does copyin and copyout deep inside stack XXX JH */
164         int error;
165         struct netmsg_pru_control msg;
166         lwkt_port_t port;
167
168         port = so->so_proto->pr_mport(so, NULL, PRU_CONTROL);
169         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
170                 lwkt_cmd_func(netmsg_pru_control), lwkt_cmd_op_none);
171         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_control;
172         msg.nm_so = so;
173         msg.nm_cmd = cmd;
174         msg.nm_data = data;
175         msg.nm_ifp = ifp;
176         msg.nm_td = td;
177         error = lwkt_domsg(port, &msg.nm_lmsg);
178         return (error);
179 #endif
180 }
181
182 int
183 so_pru_detach(struct socket *so)
184 {
185         int error;
186         struct netmsg_pru_detach msg;
187         lwkt_port_t port;
188
189         port = so->so_proto->pr_mport(so, NULL, PRU_DETACH);
190         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
191                 lwkt_cmd_func(netmsg_pru_detach), lwkt_cmd_op_none);
192         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_detach;
193         msg.nm_so = so;
194         error = lwkt_domsg(port, &msg.nm_lmsg);
195         return (error);
196 }
197
198 int
199 so_pru_disconnect(struct socket *so)
200 {
201         int error;
202         struct netmsg_pru_disconnect msg;
203         lwkt_port_t port;
204
205         port = so->so_proto->pr_mport(so, NULL, PRU_DISCONNECT);
206         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
207                 lwkt_cmd_func(netmsg_pru_disconnect), lwkt_cmd_op_none);
208         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_disconnect;
209         msg.nm_so = so;
210         error = lwkt_domsg(port, &msg.nm_lmsg);
211         return (error);
212 }
213
214 int
215 so_pru_listen(struct socket *so, struct thread *td)
216 {
217         int error;
218         struct netmsg_pru_listen msg;
219         lwkt_port_t port;
220
221         port = so->so_proto->pr_mport(so, NULL, PRU_LISTEN);
222         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
223                 lwkt_cmd_func(netmsg_pru_listen), lwkt_cmd_op_none);
224         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_listen;
225         msg.nm_so = so;
226         msg.nm_td = td;         /* used only for prison_ip() XXX JH */
227         error = lwkt_domsg(port, &msg.nm_lmsg);
228         return (error);
229 }
230
231 int
232 so_pru_peeraddr(struct socket *so, struct sockaddr **nam)
233 {
234         int error;
235         struct netmsg_pru_peeraddr msg;
236         lwkt_port_t port;
237
238         port = so->so_proto->pr_mport(so, NULL, PRU_PEERADDR);
239         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
240                 lwkt_cmd_func(netmsg_pru_peeraddr), lwkt_cmd_op_none);
241         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_peeraddr;
242         msg.nm_so = so;
243         msg.nm_nam = nam;
244         error = lwkt_domsg(port, &msg.nm_lmsg);
245         return (error);
246 }
247
248 int
249 so_pru_rcvd(struct socket *so, int flags)
250 {
251         int error;
252         struct netmsg_pru_rcvd msg;
253         lwkt_port_t port;
254
255         port = so->so_proto->pr_mport(so, NULL, PRU_RCVD);
256         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
257                 lwkt_cmd_func(netmsg_pru_rcvd), lwkt_cmd_op_none);
258         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvd;
259         msg.nm_so = so;
260         msg.nm_flags = flags;
261         error = lwkt_domsg(port, &msg.nm_lmsg);
262         return (error);
263 }
264
265 int
266 so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags)
267 {
268         int error;
269         struct netmsg_pru_rcvoob msg;
270         lwkt_port_t port;
271
272         port = so->so_proto->pr_mport(so, NULL, PRU_RCVOOB);
273         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
274                 lwkt_cmd_func(netmsg_pru_rcvoob), lwkt_cmd_op_none);
275         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvoob;
276         msg.nm_so = so;
277         msg.nm_m = m;
278         msg.nm_flags = flags;
279         error = lwkt_domsg(port, &msg.nm_lmsg);
280         return (error);
281 }
282
283 int
284 so_pru_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
285     struct mbuf *control, struct thread *td)
286 {
287         int error;
288         struct netmsg_pru_send msg;
289         lwkt_port_t port;
290
291         port = so->so_proto->pr_mport(so, NULL, PRU_SEND);
292         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
293                 lwkt_cmd_func(netmsg_pru_send), lwkt_cmd_op_none);
294         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_send;
295         msg.nm_so = so;
296         msg.nm_flags = flags;
297         msg.nm_m = m;
298         msg.nm_addr = addr;
299         msg.nm_control = control;
300         msg.nm_td = td;
301         error = lwkt_domsg(port, &msg.nm_lmsg);
302         return (error);
303 }
304
305 int
306 so_pru_sense(struct socket *so, struct stat *sb)
307 {
308         int error;
309         struct netmsg_pru_sense msg;
310         lwkt_port_t port;
311
312         port = so->so_proto->pr_mport(so, NULL, PRU_SENSE);
313         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
314                 lwkt_cmd_func(netmsg_pru_sense), lwkt_cmd_op_none);
315         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sense;
316         msg.nm_so = so;
317         msg.nm_stat = sb;
318         error = lwkt_domsg(port, &msg.nm_lmsg);
319         return (error);
320 }
321
322 int
323 so_pru_shutdown(struct socket *so)
324 {
325         int error;
326         struct netmsg_pru_shutdown msg;
327         lwkt_port_t port;
328
329         port = so->so_proto->pr_mport(so, NULL, PRU_SHUTDOWN);
330         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
331                 lwkt_cmd_func(netmsg_pru_shutdown), lwkt_cmd_op_none);
332         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_shutdown;
333         msg.nm_so = so;
334         error = lwkt_domsg(port, &msg.nm_lmsg);
335         return (error);
336 }
337
338 int
339 so_pru_sockaddr(struct socket *so, struct sockaddr **nam)
340 {
341         int error;
342         struct netmsg_pru_sockaddr msg;
343         lwkt_port_t port;
344
345         port = so->so_proto->pr_mport(so, NULL, PRU_SOCKADDR);
346         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
347                 lwkt_cmd_func(netmsg_pru_sockaddr), lwkt_cmd_op_none);
348         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sockaddr;
349         msg.nm_so = so;
350         msg.nm_nam = nam;
351         error = lwkt_domsg(port, &msg.nm_lmsg);
352         return (error);
353 }
354
355 int
356 so_pru_sopoll(struct socket *so, int events, struct ucred *cred,
357     struct thread *td)
358 {
359         int error;
360         struct netmsg_pru_sopoll msg;
361         lwkt_port_t port;
362
363         port = so->so_proto->pr_mport(so, NULL, PRU_SOPOLL);
364         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
365                 lwkt_cmd_func(netmsg_pru_sopoll), lwkt_cmd_op_none);
366         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sopoll;
367         msg.nm_so = so;
368         msg.nm_events = events;
369         msg.nm_cred = cred;
370         msg.nm_td = td;
371         error = lwkt_domsg(port, &msg.nm_lmsg);
372         return (error);
373 }
374
375 int
376 so_pr_ctloutput(struct socket *so, struct sockopt *sopt)
377 {
378         return ((*so->so_proto->pr_ctloutput)(so, sopt));
379 #ifdef gag      /* does copyin and copyout deep inside stack XXX JH */
380         struct netmsg_pr_ctloutput msg;
381         lwkt_port_t port;
382         int error;
383
384         port = so->so_proto->pr_mport(so, NULL);
385         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
386                 lwkt_cmd_func(netmsg_pru_ctloutput), lwkt_cmd_op_none);
387         msg.nm_prfn = so->so_proto->pr_ctloutput;
388         msg.nm_so = so;
389         msg.nm_sopt = sopt;
390         error = lwkt_domsg(port, &msg.nm_lmsg);
391         return (error);
392 #endif
393 }
394
395 /*
396  * If we convert all the protosw pr_ functions for all the protocols
397  * to take a message directly, this layer can go away.  For the moment
398  * our dispatcher ignores the return value, but since we are handling
399  * the replymsg ourselves we return EASYNC by convention.
400  */
401 int
402 netmsg_pru_abort(lwkt_msg_t msg)
403 {
404         struct netmsg_pru_abort *nm = (void *)msg;
405
406         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
407         return(EASYNC);
408 }
409
410 #ifdef notused
411 int
412 netmsg_pru_accept(lwkt_msg_t msg)
413 {
414         struct netmsg_pru_accept *nm = (void *)msg;
415
416         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam));
417         return(EASYNC);
418 }
419 #endif
420
421 int
422 netmsg_pru_attach(lwkt_msg_t msg)
423 {
424         struct netmsg_pru_attach *nm = (void *)msg;
425
426         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_proto, nm->nm_ai));
427         return(EASYNC);
428 }
429
430 int
431 netmsg_pru_bind(lwkt_msg_t msg)
432 {
433         struct netmsg_pru_bind *nm = (void *)msg;
434
435         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam, nm->nm_td));
436         return(EASYNC);
437 }
438
439 int
440 netmsg_pru_connect(lwkt_msg_t msg)
441 {
442         struct netmsg_pru_connect *nm = (void *)msg;
443
444         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam, nm->nm_td));
445         return(EASYNC);
446 }
447
448 int
449 netmsg_pru_connect2(lwkt_msg_t msg)
450 {
451         struct netmsg_pru_connect2 *nm = (void *)msg;
452
453         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so1, nm->nm_so2));
454         return(EASYNC);
455 }
456
457 int
458 netmsg_pru_control(lwkt_msg_t msg)
459 {
460         struct netmsg_pru_control *nm = (void *)msg;
461         int error;
462
463         error = nm->nm_prufn(nm->nm_so, nm->nm_cmd, nm->nm_data,
464                                 nm->nm_ifp, nm->nm_td);
465         lwkt_replymsg(msg, error);
466         return(EASYNC);
467 }
468
469 int
470 netmsg_pru_detach(lwkt_msg_t msg)
471 {
472         struct netmsg_pru_detach *nm = (void *)msg;
473
474         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
475         return(EASYNC);
476 }
477
478 int
479 netmsg_pru_disconnect(lwkt_msg_t msg)
480 {
481         struct netmsg_pru_disconnect *nm = (void *)msg;
482
483         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
484         return(EASYNC);
485 }
486
487 int
488 netmsg_pru_listen(lwkt_msg_t msg)
489 {
490         struct netmsg_pru_listen *nm = (void *)msg;
491
492         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_td));
493         return(EASYNC);
494 }
495
496 int
497 netmsg_pru_peeraddr(lwkt_msg_t msg)
498 {
499         struct netmsg_pru_peeraddr *nm = (void *)msg;
500
501         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam));
502         return(EASYNC);
503 }
504
505 int
506 netmsg_pru_rcvd(lwkt_msg_t msg)
507 {
508         struct netmsg_pru_rcvd *nm = (void *)msg;
509
510         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_flags));
511         return(EASYNC);
512 }
513
514 int
515 netmsg_pru_rcvoob(lwkt_msg_t msg)
516 {
517         struct netmsg_pru_rcvoob *nm = (void *)msg;
518
519         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_m, nm->nm_flags));
520         return(EASYNC);
521 }
522
523 int
524 netmsg_pru_send(lwkt_msg_t msg)
525 {
526         struct netmsg_pru_send *nm = (void *)msg;
527         int error;
528
529         error = nm->nm_prufn(nm->nm_so, nm->nm_flags, nm->nm_m,
530                                 nm->nm_addr, nm->nm_control, nm->nm_td);
531         lwkt_replymsg(msg, error);
532         return(EASYNC);
533 }
534
535 int
536 netmsg_pru_sense(lwkt_msg_t msg)
537 {
538         struct netmsg_pru_sense *nm = (void *)msg;
539
540         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_stat));
541         return(EASYNC);
542 }
543
544 int
545 netmsg_pru_shutdown(lwkt_msg_t msg)
546 {
547         struct netmsg_pru_shutdown *nm = (void *)msg;
548
549         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
550         return(EASYNC);
551 }
552
553 int
554 netmsg_pru_sockaddr(lwkt_msg_t msg)
555 {
556         struct netmsg_pru_sockaddr *nm = (void *)msg;
557
558         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam));
559         return(EASYNC);
560 }
561
562 int
563 netmsg_pru_sopoll(lwkt_msg_t msg)
564 {
565         struct netmsg_pru_sopoll *nm = (void *)msg;
566         int error;
567
568         error = nm->nm_prufn(nm->nm_so, nm->nm_events, nm->nm_cred, nm->nm_td);
569         lwkt_replymsg(msg, error);
570         return(EASYNC);
571 }
572
573 int
574 netmsg_pr_ctloutput(lwkt_msg_t msg)
575 {
576         struct netmsg_pr_ctloutput *nm = (void *)msg;
577
578         lwkt_replymsg(msg, nm->nm_prfn(nm->nm_so, nm->nm_sopt));
579         return(EASYNC);
580 }
581
582 int
583 netmsg_pr_timeout(lwkt_msg_t msg)
584 {
585         struct netmsg_pr_timeout *nm = (void *)msg;
586
587         lwkt_replymsg(msg, nm->nm_prfn());
588         return(EASYNC);
589 }
590
591 /*
592  * Handle a predicate event request.  This function is only called once
593  * when the predicate message queueing request is received.
594  */
595 int
596 netmsg_so_notify(lwkt_msg_t lmsg)
597 {
598         struct netmsg_so_notify *msg = (void *)lmsg;
599         struct sockbuf *sb;
600
601         sb = (msg->nm_etype & NM_REVENT) ?
602                         &msg->nm_so->so_rcv :
603                         &msg->nm_so->so_snd;
604
605         /*
606          * Reply immediately if the event has occured, otherwise queue the
607          * request.
608          */
609         if (msg->nm_predicate((struct netmsg *)msg)) {
610                 lwkt_replymsg(lmsg, lmsg->ms_error);
611         } else {
612                 TAILQ_INSERT_TAIL(&sb->sb_sel.si_mlist, msg, nm_list);
613                 sb->sb_flags |= SB_MEVENT;
614         }
615         return(EASYNC);
616 }
617
618 /*
619  * Predicate requests can be aborted.  This function is only called once
620  * and will interlock against processing/reply races (since such races
621  * occur on the same thread that controls the port where the abort is 
622  * requeued).
623  */
624 int
625 netmsg_so_notify_abort(lwkt_msg_t lmsg)
626 {
627         struct netmsg_so_notify *msg = (void *)lmsg;
628         struct sockbuf *sb;
629
630         sb = (msg->nm_etype & NM_REVENT) ?
631                         &msg->nm_so->so_rcv :
632                         &msg->nm_so->so_snd;
633         TAILQ_REMOVE(&sb->sb_sel.si_mlist, msg, nm_list);
634         lwkt_replymsg(lmsg, EINTR);
635         return(EASYNC);
636 }
637