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