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