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.25 2008/09/02 16:17:52 dillon 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 lwkt_port_t port; 63 64 KKASSERT(so->so_state & SS_ABORTING); 65 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_ABORT); 66 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 67 0, netmsg_pru_abort); 68 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort; 69 msg.nm_so = so; 70 (void)lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 71 } 72 73 /* 74 * Abort a socket and free it, asynchronously. Called from 75 * soaborta() only. 76 * 77 * The SS_ABORTING flag must already be set. 78 */ 79 void 80 so_pru_aborta(struct socket *so) 81 { 82 struct netmsg_pru_abort *msg; 83 lwkt_port_t port; 84 85 KKASSERT(so->so_state & SS_ABORTING); 86 msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO); 87 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_ABORT); 88 netmsg_init(&msg->nm_netmsg, &netisr_afree_rport, 89 0, netmsg_pru_abort); 90 msg->nm_prufn = so->so_proto->pr_usrreqs->pru_abort; 91 msg->nm_so = so; 92 lwkt_sendmsg(port, &msg->nm_netmsg.nm_lmsg); 93 } 94 95 int 96 so_pru_accept(struct socket *so, struct sockaddr **nam) 97 { 98 /* Block (memory allocation) in process context. XXX JH */ 99 return ((*so->so_proto->pr_usrreqs->pru_accept)(so, nam)); 100 101 #ifdef notdef 102 int error; 103 struct netmsg_pru_accept msg; 104 lwkt_port_t port; 105 106 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_ACCEPT); 107 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 108 netmsg_pru_accept); 109 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_accept; 110 msg.nm_so = so; 111 msg.nm_nam = nam; 112 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 113 return (error); 114 #endif 115 } 116 117 int 118 so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai) 119 { 120 int error; 121 struct netmsg_pru_attach msg; 122 lwkt_port_t port; 123 124 port = so->so_proto->pr_mport(NULL, NULL, NULL, PRU_ATTACH); 125 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 126 netmsg_pru_attach); 127 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_attach; 128 msg.nm_so = so; 129 msg.nm_proto = proto; 130 msg.nm_ai = ai; 131 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 132 return (error); 133 } 134 135 int 136 so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 137 { 138 int error; 139 struct netmsg_pru_bind msg; 140 lwkt_port_t port; 141 142 /* Send mesg to thread for new address. */ 143 port = so->so_proto->pr_mport(NULL, nam, NULL, PRU_BIND); 144 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 145 netmsg_pru_bind); 146 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_bind; 147 msg.nm_so = so; 148 msg.nm_nam = nam; 149 msg.nm_td = td; /* used only for prison_ip() XXX JH */ 150 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 151 return (error); 152 } 153 154 int 155 so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 156 { 157 int error; 158 struct netmsg_pru_connect msg; 159 lwkt_port_t port; 160 161 port = so->so_proto->pr_mport(so, nam, NULL, PRU_CONNECT); 162 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 163 netmsg_pru_connect); 164 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_connect; 165 msg.nm_so = so; 166 msg.nm_nam = nam; 167 msg.nm_td = td; 168 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 169 return (error); 170 } 171 172 int 173 so_pru_connect2(struct socket *so1, struct socket *so2) 174 { 175 int error; 176 struct netmsg_pru_connect2 msg; 177 lwkt_port_t port; 178 179 port = so1->so_proto->pr_mport(so1, NULL, NULL, PRU_CONNECT2); 180 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 181 netmsg_pru_connect2); 182 msg.nm_prufn = so1->so_proto->pr_usrreqs->pru_connect2; 183 msg.nm_so1 = so1; 184 msg.nm_so2 = so2; 185 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 186 return (error); 187 } 188 189 int 190 so_pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) 191 { 192 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, ifp, 193 curthread)); 194 #ifdef gag /* does copyin and copyout deep inside stack XXX JH */ 195 int error; 196 struct netmsg_pru_control msg; 197 lwkt_port_t port; 198 199 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_CONTROL); 200 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 201 netmsg_pru_control); 202 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_control; 203 msg.nm_so = so; 204 msg.nm_cmd = cmd; 205 msg.nm_data = data; 206 msg.nm_ifp = ifp; 207 msg.nm_td = td; 208 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 209 return (error); 210 #endif 211 } 212 213 int 214 so_pru_detach(struct socket *so) 215 { 216 int error; 217 struct netmsg_pru_detach msg; 218 lwkt_port_t port; 219 220 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_DETACH); 221 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 222 netmsg_pru_detach); 223 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_detach; 224 msg.nm_so = so; 225 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 226 return (error); 227 } 228 229 int 230 so_pru_disconnect(struct socket *so) 231 { 232 int error; 233 struct netmsg_pru_disconnect msg; 234 lwkt_port_t port; 235 236 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_DISCONNECT); 237 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 238 netmsg_pru_disconnect); 239 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_disconnect; 240 msg.nm_so = so; 241 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 242 return (error); 243 } 244 245 int 246 so_pru_listen(struct socket *so, struct thread *td) 247 { 248 int error; 249 struct netmsg_pru_listen msg; 250 lwkt_port_t port; 251 252 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_LISTEN); 253 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 254 netmsg_pru_listen); 255 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_listen; 256 msg.nm_so = so; 257 msg.nm_td = td; /* used only for prison_ip() XXX JH */ 258 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 259 return (error); 260 } 261 262 int 263 so_pru_peeraddr(struct socket *so, struct sockaddr **nam) 264 { 265 int error; 266 struct netmsg_pru_peeraddr msg; 267 lwkt_port_t port; 268 269 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_PEERADDR); 270 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 271 netmsg_pru_peeraddr); 272 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_peeraddr; 273 msg.nm_so = so; 274 msg.nm_nam = nam; 275 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 276 return (error); 277 } 278 279 int 280 so_pru_rcvd(struct socket *so, int flags) 281 { 282 int error; 283 struct netmsg_pru_rcvd msg; 284 lwkt_port_t port; 285 286 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_RCVD); 287 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 288 netmsg_pru_rcvd); 289 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvd; 290 msg.nm_so = so; 291 msg.nm_flags = flags; 292 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 293 return (error); 294 } 295 296 int 297 so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags) 298 { 299 int error; 300 struct netmsg_pru_rcvoob msg; 301 lwkt_port_t port; 302 303 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_RCVOOB); 304 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 305 netmsg_pru_rcvoob); 306 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvoob; 307 msg.nm_so = so; 308 msg.nm_m = m; 309 msg.nm_flags = flags; 310 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 311 return (error); 312 } 313 314 int 315 so_pru_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 316 struct mbuf *control, struct thread *td) 317 { 318 int error; 319 struct netmsg_pru_send msg; 320 lwkt_port_t port; 321 322 port = so->so_proto->pr_mport(so, addr, &m, PRU_SEND); 323 if (port == NULL) { 324 KKASSERT(m == NULL); 325 return EINVAL; 326 } 327 328 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 329 netmsg_pru_send); 330 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_send; 331 msg.nm_so = so; 332 msg.nm_flags = flags; 333 msg.nm_m = m; 334 msg.nm_addr = addr; 335 msg.nm_control = control; 336 msg.nm_td = td; 337 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 338 return (error); 339 } 340 341 int 342 so_pru_sense(struct socket *so, struct stat *sb) 343 { 344 int error; 345 struct netmsg_pru_sense msg; 346 lwkt_port_t port; 347 348 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_SENSE); 349 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 350 netmsg_pru_sense); 351 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sense; 352 msg.nm_so = so; 353 msg.nm_stat = sb; 354 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 355 return (error); 356 } 357 358 int 359 so_pru_shutdown(struct socket *so) 360 { 361 int error; 362 struct netmsg_pru_shutdown msg; 363 lwkt_port_t port; 364 365 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_SHUTDOWN); 366 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 367 netmsg_pru_shutdown); 368 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_shutdown; 369 msg.nm_so = so; 370 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 371 return (error); 372 } 373 374 int 375 so_pru_sockaddr(struct socket *so, struct sockaddr **nam) 376 { 377 int error; 378 struct netmsg_pru_sockaddr msg; 379 lwkt_port_t port; 380 381 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_SOCKADDR); 382 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 383 netmsg_pru_sockaddr); 384 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sockaddr; 385 msg.nm_so = so; 386 msg.nm_nam = nam; 387 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 388 return (error); 389 } 390 391 int 392 so_pru_sopoll(struct socket *so, int events, struct ucred *cred) 393 { 394 int error; 395 struct netmsg_pru_sopoll msg; 396 lwkt_port_t port; 397 398 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_SOPOLL); 399 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 400 netmsg_pru_sopoll); 401 msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sopoll; 402 msg.nm_so = so; 403 msg.nm_events = events; 404 msg.nm_cred = cred; 405 msg.nm_td = curthread; 406 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 407 return (error); 408 } 409 410 int 411 so_pru_ctloutput(struct socket *so, struct sockopt *sopt) 412 { 413 struct netmsg_pru_ctloutput msg; 414 lwkt_port_t port; 415 int error; 416 417 KKASSERT(!sopt->sopt_val || kva_p(sopt->sopt_val)); 418 port = so->so_proto->pr_mport(so, NULL, NULL, PRU_CTLOUTPUT); 419 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 420 netmsg_pru_ctloutput); 421 /* TBD: move pr_ctloutput to pr_usrreqs */ 422 msg.nm_prufn = so->so_proto->pr_ctloutput; 423 msg.nm_so = so; 424 msg.nm_sopt = sopt; 425 error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0); 426 return (error); 427 } 428 429 /* 430 * If we convert all the protosw pr_ functions for all the protocols 431 * to take a message directly, this layer can go away. For the moment 432 * our dispatcher ignores the return value, but since we are handling 433 * the replymsg ourselves we return EASYNC by convention. 434 */ 435 436 /* 437 * Abort and destroy a socket. 438 */ 439 void 440 netmsg_pru_abort(netmsg_t msg) 441 { 442 struct netmsg_pru_abort *nm = (void *)msg; 443 struct socket *so = nm->nm_so; 444 int error; 445 446 KKASSERT(so->so_state & SS_ABORTING); 447 so->so_state &= ~SS_ABORTING; 448 error = nm->nm_prufn(so); 449 if (error) 450 sofree(so); 451 lwkt_replymsg(&msg->nm_lmsg, error); 452 } 453 454 #ifdef notused 455 void 456 netmsg_pru_accept(netmsg_t msg) 457 { 458 struct netmsg_pru_accept *nm = (void *)msg; 459 460 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_nam)); 461 } 462 #endif 463 464 void 465 netmsg_pru_attach(netmsg_t msg) 466 { 467 struct netmsg_pru_attach *nm = (void *)msg; 468 469 lwkt_replymsg(&msg->nm_lmsg, 470 nm->nm_prufn(nm->nm_so, nm->nm_proto, nm->nm_ai)); 471 } 472 473 void 474 netmsg_pru_bind(netmsg_t msg) 475 { 476 struct netmsg_pru_bind *nm = (void *)msg; 477 478 lwkt_replymsg(&msg->nm_lmsg, 479 nm->nm_prufn(nm->nm_so, nm->nm_nam, nm->nm_td)); 480 } 481 482 void 483 netmsg_pru_connect(netmsg_t msg) 484 { 485 struct netmsg_pru_connect *nm = (void *)msg; 486 487 lwkt_replymsg(&msg->nm_lmsg, 488 nm->nm_prufn(nm->nm_so, nm->nm_nam, nm->nm_td)); 489 } 490 491 void 492 netmsg_pru_connect2(netmsg_t msg) 493 { 494 struct netmsg_pru_connect2 *nm = (void *)msg; 495 496 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so1, nm->nm_so2)); 497 } 498 499 void 500 netmsg_pru_control(netmsg_t msg) 501 { 502 struct netmsg_pru_control *nm = (void *)msg; 503 int error; 504 505 error = nm->nm_prufn(nm->nm_so, nm->nm_cmd, nm->nm_data, 506 nm->nm_ifp, nm->nm_td); 507 lwkt_replymsg(&msg->nm_lmsg, error); 508 } 509 510 void 511 netmsg_pru_detach(netmsg_t msg) 512 { 513 struct netmsg_pru_detach *nm = (void *)msg; 514 515 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so)); 516 } 517 518 void 519 netmsg_pru_disconnect(netmsg_t msg) 520 { 521 struct netmsg_pru_disconnect *nm = (void *)msg; 522 523 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so)); 524 } 525 526 void 527 netmsg_pru_listen(netmsg_t msg) 528 { 529 struct netmsg_pru_listen *nm = (void *)msg; 530 531 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_td)); 532 } 533 534 void 535 netmsg_pru_peeraddr(netmsg_t msg) 536 { 537 struct netmsg_pru_peeraddr *nm = (void *)msg; 538 539 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_nam)); 540 } 541 542 void 543 netmsg_pru_rcvd(netmsg_t msg) 544 { 545 struct netmsg_pru_rcvd *nm = (void *)msg; 546 547 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_flags)); 548 } 549 550 void 551 netmsg_pru_rcvoob(netmsg_t msg) 552 { 553 struct netmsg_pru_rcvoob *nm = (void *)msg; 554 555 lwkt_replymsg(&msg->nm_lmsg, 556 nm->nm_prufn(nm->nm_so, nm->nm_m, nm->nm_flags)); 557 } 558 559 void 560 netmsg_pru_send(netmsg_t msg) 561 { 562 struct netmsg_pru_send *nm = (void *)msg; 563 int error; 564 565 error = nm->nm_prufn(nm->nm_so, nm->nm_flags, nm->nm_m, 566 nm->nm_addr, nm->nm_control, nm->nm_td); 567 lwkt_replymsg(&msg->nm_lmsg, error); 568 } 569 570 void 571 netmsg_pru_sense(netmsg_t msg) 572 { 573 struct netmsg_pru_sense *nm = (void *)msg; 574 575 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_stat)); 576 } 577 578 void 579 netmsg_pru_shutdown(netmsg_t msg) 580 { 581 struct netmsg_pru_shutdown *nm = (void *)msg; 582 583 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so)); 584 } 585 586 void 587 netmsg_pru_sockaddr(netmsg_t msg) 588 { 589 struct netmsg_pru_sockaddr *nm = (void *)msg; 590 591 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_nam)); 592 } 593 594 void 595 netmsg_pru_sopoll(netmsg_t msg) 596 { 597 struct netmsg_pru_sopoll *nm = (void *)msg; 598 int error; 599 600 error = nm->nm_prufn(nm->nm_so, nm->nm_events, nm->nm_cred, nm->nm_td); 601 lwkt_replymsg(&msg->nm_lmsg, error); 602 } 603 604 void 605 netmsg_pru_ctloutput(netmsg_t msg) 606 { 607 struct netmsg_pru_ctloutput *nm = (void *)msg; 608 609 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so, nm->nm_sopt)); 610 } 611 612 void 613 netmsg_pr_timeout(netmsg_t msg) 614 { 615 struct netmsg_pr_timeout *nm = (void *)msg; 616 617 lwkt_replymsg(&msg->nm_lmsg, nm->nm_prfn()); 618 } 619 620 /* 621 * Handle a predicate event request. This function is only called once 622 * when the predicate message queueing request is received. 623 */ 624 void 625 netmsg_so_notify(netmsg_t netmsg) 626 { 627 struct netmsg_so_notify *msg = (void *)netmsg; 628 struct signalsockbuf *ssb; 629 630 ssb = (msg->nm_etype & NM_REVENT) ? 631 &msg->nm_so->so_rcv : 632 &msg->nm_so->so_snd; 633 634 /* 635 * Reply immediately if the event has occured, otherwise queue the 636 * request. 637 */ 638 if (msg->nm_predicate(&msg->nm_netmsg)) { 639 lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, 640 msg->nm_netmsg.nm_lmsg.ms_error); 641 } else { 642 TAILQ_INSERT_TAIL(&ssb->ssb_sel.si_mlist, msg, nm_list); 643 ssb->ssb_flags |= SSB_MEVENT; 644 } 645 } 646 647 /* 648 * Called by doio when trying to abort a netmsg_so_notify message. 649 * Unlike the other functions this one is dispatched directly by 650 * the LWKT subsystem, so it takes a lwkt_msg_t as an argument. 651 * 652 * The original message, lmsg, is under the control of the caller and 653 * will not be destroyed until we return so we can safely reference it 654 * in our synchronous abort request. 655 * 656 * This part of the abort request occurs on the originating cpu which 657 * means we may race the message flags and the original message may 658 * not even have been processed by the target cpu yet. 659 */ 660 void 661 netmsg_so_notify_doabort(lwkt_msg_t lmsg) 662 { 663 struct netmsg_so_notify_abort msg; 664 665 if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) { 666 netmsg_init(&msg.nm_netmsg, &curthread->td_msgport, 0, 667 netmsg_so_notify_abort); 668 msg.nm_notifymsg = (void *)lmsg; 669 lwkt_domsg(lmsg->ms_target_port, &msg.nm_netmsg.nm_lmsg, 0); 670 } 671 } 672 673 /* 674 * Predicate requests can be aborted. This function is only called once 675 * and will interlock against processing/reply races (since such races 676 * occur on the same thread that controls the port where the abort is 677 * requeued). 678 * 679 * This part of the abort request occurs on the target cpu. The message 680 * flags must be tested again in case the test that we did on the 681 * originating cpu raced. Since messages are handled in sequence, the 682 * original message will have already been handled by the loop and either 683 * replied to or queued. 684 * 685 * We really only need to interlock with MSGF_REPLY (a bit that is set on 686 * our cpu when we reply). Note that MSGF_DONE is not set until the 687 * reply reaches the originating cpu. Test both bits anyway. 688 */ 689 void 690 netmsg_so_notify_abort(netmsg_t netmsg) 691 { 692 struct netmsg_so_notify_abort *abrtmsg = (void *)netmsg; 693 struct netmsg_so_notify *msg = abrtmsg->nm_notifymsg; 694 struct signalsockbuf *ssb; 695 696 /* 697 * The original notify message is not destroyed until after the 698 * abort request is returned, so we can check its state. 699 */ 700 if ((msg->nm_netmsg.nm_lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) { 701 ssb = (msg->nm_etype & NM_REVENT) ? 702 &msg->nm_so->so_rcv : 703 &msg->nm_so->so_snd; 704 TAILQ_REMOVE(&ssb->ssb_sel.si_mlist, msg, nm_list); 705 lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, EINTR); 706 } 707 708 /* 709 * Reply to the abort message 710 */ 711 lwkt_replymsg(&abrtmsg->nm_netmsg.nm_lmsg, 0); 712 } 713 714