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 722