1.\" 2.\" Copyright (c) 2012 The DragonFly Project. All rights reserved. 3.\" 4.\" This code is derived from software contributed to The DragonFly Project 5.\" by Nuno Antunes <nuno.antunes@gmail.com>. 6.\" 7.\" Redistribution and use in source and binary forms, with or without 8.\" modification, are permitted provided that the following conditions 9.\" are met: 10.\" 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 15.\" the documentation and/or other materials provided with the 16.\" distribution. 17.\" 3. Neither the name of The DragonFly Project nor the names of its 18.\" contributors may be used to endorse or promote products derived 19.\" from this software without specific, prior written permission. 20.\" 21.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32.\" SUCH DAMAGE. 33.\" 34.Dd September 17, 2012 35.Dt MSGPORT 9 36.Os 37.Sh NAME 38.Nm lwkt_initport_thread , 39.Nm lwkt_initport_spin , 40.Nm lwkt_initport_serialize , 41.Nm lwkt_initport_panic , 42.Nm lwkt_initport_replyonly_null , 43.Nm lwkt_initport_replyonly , 44.Nm lwkt_initport_putonly , 45.Nm lwkt_sendmsg , 46.Nm lwkt_domsg , 47.Nm lwkt_forwardmsg , 48.Nm lwkt_abortmsg , 49.Nm lwkt_initmsg , 50.Nm lwkt_initmsg_abortable , 51.Nm lwkt_beginmsg , 52.Nm lwkt_replymsg , 53.Nm lwkt_getport , 54.Nm lwkt_waitport , 55.Nm lwkt_waitmsg , 56.Nm lwkt_checkmsg , 57.Nm lwkt_dropmsg 58.Nd LWKT message passing interface 59.Sh SYNOPSIS 60.In sys/msgport.h 61.Ft void 62.Fn lwkt_initport_thread "lwkt_port_t port" "struct thread *td" 63.Ft void 64.Fn lwkt_initport_spin "lwkt_port_t port" "struct thread *td" 65.Ft void 66.Fn lwkt_initport_serialize "lwkt_port_t port" "struct lwkt_serialize *slz" 67.Ft void 68.Fn lwkt_initport_panic "lwkt_port_t port" 69.Ft void 70.Fn lwkt_initport_replyonly_null "lwkt_port_t port" 71.Ft void 72.Fn lwkt_initport_replyonly "lwkt_port_t port" "void (*rportfn)(lwkt_port_t, lwkt_msg_t)" 73.Ft void 74.Fn lwkt_initport_putonly "lwkt_port_t port" "int (*pportfn)(lwkt_port_t, lwkt_msg_t)" 75.Ft void 76.Fn lwkt_sendmsg "lwkt_port_t port" "lwkt_msg_t msg" 77.Ft int 78.Fn lwkt_domsg "lwkt_port_t port" "lwkt_msg_t msg" "int flags" 79.Ft int 80.Fn lwkt_forwardmsg "lwkt_port_t port" "lwkt_msg_t msg" 81.Ft void 82.Fn lwkt_abortmsg "lwkt_msg_t msg" 83.In sys/msgport2.h 84.Ft void 85.Fn lwkt_initmsg "lwkt_msg_t msg" "lwkt_port_t rport" "int flags" 86.Ft void 87.Fn lwkt_initmsg_abortable "lwkt_msg_t msg" "lwkt_port_t rport" "int flags" "void (*abortfn)(lwkt_msg_t)" 88.Ft int 89.Fn lwkt_beginmsg "lwkt_port_t port" "lwkt_msg_t msg" 90.Ft void 91.Fn lwkt_replymsg "lwkt_msg_t msg" "int error" 92.Ft void * 93.Fn lwkt_getport "lwkt_port_t port" 94.Ft void * 95.Fn lwkt_waitport "lwkt_port_t port" "int flags" 96.Ft int 97.Fn lwkt_waitmsg "lwkt_msg_t msg" "int flags" 98.Ft int 99.Fn lwkt_checkmsg "lwkt_msg_t msg" 100.Ft void 101.Fn lwkt_dropmsg "lwkt_msg_t msg" 102.Sh DESCRIPTION 103Light weight kernel threads in 104.Dx 105may use a message passing interface to communicate with each other. 106Messages are sent to message ports. 107All light weight kernel threads have a built-in message port, but you may create 108additional ports if necessary. 109The following types of message ports are available: 110.Bl -bullet 111.It 112thread ports 113.It 114spin ports 115.It 116serializer ports 117.El 118.Pp 119Ports of type 120.Sq thread 121are owned by a single light weight kernel thread. 122When a message is sent to a port of type 123.Sq thread , 124only the owner of that port is allowed to retrieve the message from it. 125When a message is sent to a port of type 126.Sq spin 127or to a port of type 128.Sq serializer , 129multiple threads are allowed to check that port for new 130messages and compete to retrieve them. 131You define the port type when you initialize the port. 132By default, the built-in port of every light weight kernel thread is 133automatically initialized to type 134.Sq thread . 135.Pp 136When a message is sent, the receiver should normally send back a reply. 137The reply is sent to the reply port that is registered on the original message. 138Messages can be replied to synchronously or asynchronously. 139The sender may request a synchronous or asynchronous reply to the message, 140however the target port will ultimately decide how the message will be treated. 141.Sh MESSAGE FUNCTIONS 142Messages must be initialized before being used. 143The 144.Fn lwkt_initmsg 145function initializes a message. 146The 147.Fa rport 148argument identifies the reply port which will be used for asynchronous replies. 149The 150.Fa flags 151argument sets any required flags for this message. 152Flags passed this way will simply be or'ed to any already existing flags on the 153message. 154.Pp 155The 156.Fn lwkt_initmsg_abortable 157function is similar to 158.Fn lwkt_initmsg 159but it takes an additional parameter 160.Fa abortfn 161which defines the abort function for this message. 162.Pp 163The 164.Fn lwkt_sendmsg 165function requests an asynchronous reply, sends the message and returns 166immediately. 167Under normal circumstances, users of this function may always expect the reply 168to be queued to the reply port registered on the message. 169The 170.Fa port 171argument defines the target port to which the 172.Fa msg 173message will be sent. 174.Pp 175The 176.Fn lwkt_domsg 177function requests a synchronous reply, sends the message and does not return 178until the message has been replied to. 179If the target port supports synchronous reply, this function will return that 180reply immediately. 181If not, and this is the most common case, this function will block and wait for the 182reply to arrive and then return it. 183The 184.Fa port 185argument defines the target port to which the 186.Fa msg 187message will be sent. 188.Pp 189The 190.Fn lwkt_replymsg 191function replies to a message that was processed asynchronously by the target 192port. 193This function is used by the thread on the receiving side. 194The 195.Fa msg 196argument is the message being replied to and the 197.Fa error 198argument is the actual response to send back. 199.Pp 200The 201.Fn lwkt_forwardmsg 202simply forwards a message to another port. 203The 204.Fa port 205argument defines the target port to which the 206.Fa msg 207message will be sent. 208.Pp 209If a message has been initialized as abortable, you can use the 210.Fn lwkt_abortmsg 211function to try to abort it. 212The 213.Fa abortfn 214passed upon the initialisation with 215.Fn lwkt_initmsg_abortable 216will be called by this function. 217.Pp 218The 219.Fn lwkt_dropmsg 220will dequeue the specified message from the target port it was sent to and makes 221it look like it was never sent. 222This function can only be used by the thread that owns the target port. 223.Sh PORT FUNCTIONS 224The 225.Fn lwkt_initport_thread 226initializes the specified 227.Fa port 228with the default 229.Sq thread 230port type handlers. 231The 232.Fa td 233argument defines the owner thread of the port and only that thread is allowed to 234receive messages on it. 235.Pp 236The 237.Fn lwkt_initport_spin 238initializes the specified 239.Fa port 240with the default 241.Sq spin 242port type handlers. 243The 244.Fa td 245argument defines the owner thread of the port, for cases where thread built-in 246ports are initialized as 247.Sq spin 248ports. 249If 250.Dv NULL 251is passed, then the port will not have a defined owner, so functions like 252.Fn lwkt_dropmsg 253will not be available for this port. 254This function will also initialize the embedded spinlock within the 255.Vt lwkt_port 256structure which will protect subsequent port access. 257.Pp 258The 259.Fn lwkt_initport_serialize 260function initializes the specified 261.Fa port 262with the default 263.Sq serializer 264port type handlers. 265The subsequent port access will be protected by the passed 266.Fa slz 267serializer lock. 268.Pp 269The 270.Fn lwkt_getport 271function checks the specified 272.Fa port 273for available messages, dequeues the first one and returns it. 274If no messages are available then 275.Dv NULL 276is returned instead. 277This function is used by threads on the receiving side. 278.Pp 279The 280.Fn lwkt_waitport 281function checks the specified 282.Fa port 283for available messages, dequeues the first one and returns it. 284If no messages are available then the caller thread will sleep until a message 285arrives on the specified port. 286The 287.Fa flags 288argument defines the flags used for the sleep. 289This function is used by threads on the receiving side. 290.Sh SPECIAL PORT INITIALIZERS 291The 292.Fn lwkt_initport_replyonly 293function initializes a 294.Fa port 295which is used only as reply port and may have a custom reply port handler. 296The reply port handler is specified with the 297.Fa rportfn 298argument. 299All the other handlers will panic the system if they are called. 300This initializer is normally used on ports for freeing resources after the 301messages have fulfilled their purpose. 302.Pp 303The 304.Fn lwkt_initport_replyonly_null 305function initializes a 306.Fa port 307which is used only as reply port. 308The reply port handler will simply mark the message as being done and will not 309attempt to queue it. 310All the other handlers will panic the system if they are called. 311.Pp 312The 313.Fn lwkt_initport_putonly 314function initializes a 315.Fa port 316which is used only as target port. 317The putport handler is specified with the 318.Fa pportfn 319argument. 320All the other handlers will panic the system if they are called. 321.Pp 322The 323.Fn lwkt_initport_panic 324function initializes a 325.Fa port 326which will panic the system if any of its handlers are called. 327This function is sometimes used to initialize a reply-only port which does not 328expect the messages to be replied to, e.g.\& when the messages should be 329consumed by the receiving thread and never replied back. 330.Sh INTERNAL MESSAGE FUNCTIONS 331The following functions are used only by the infrastructure, you should not 332need to use them directly unless in very rare cases. 333.Pp 334The 335.Fn lwkt_beginmsg 336function simply calls the target port's putport handler. 337This function is only called by the 338.Fn lwkt_sendmsg 339and 340.Fn lwkt_replymsg 341functions. 342The putport handler returns 343.Er EASYNC 344for messages processed asynchronously or any other value for messages processed 345synchronously. 346That return value of the putport handler is propagated by this function. 347The 348.Fa port 349argument defines the target port to which the 350.Fa msg 351message will be sent. 352.Pp 353The 354.Fn lwkt_waitmsg 355function puts the caller to sleep until the specified 356.Fa msg 357message has been replied to. 358The 359.Fa flags 360argument defines the flags used for the sleep. 361.Sh IMPLEMENTATION NOTES 362All the default putport handlers (used when a message is sent) currently 363implement asynchronous putports only, i.e.\& all 364.Fn *_putport 365handlers return 366.Er EASYNC . 367You can still have synchronous putport handlers (which are run in the sender's 368context) but you have to implement the function yourself and then override the 369default. 370.Pp 371Port handler functions can be overridden with custom functions if required. 372You can override the default putport handler by either using the 373.Fn lwkt_initport_putonly 374initializer, or by manipulating the mp_putport handler pointer directly on the 375.Vt lwkt_port 376structure. 377.Pp 378There is one such case where the putport handler is overridden in 379.Pa sys/net/netisr.c . 380In that case, the putport handler is overridden to detect a loopback message 381(when the target port belongs to the sending thread). 382This special putport handler turns the sent message into a direct function call 383instead of queueing it to the port. 384.Pp 385The 386.Fn lwkt_replymsg 387function works differently depending on the original message request. 388If the 389message was originally an asynchronous request, the reply will be queued to the 390sender's reply port. 391If the message was originally a synchronous request, then 392this function will just write the error response on the message and wake up the 393waiter without queueing the message to the reply port. 394There is no need to queue in the synchronous request case because the original 395sender had blocked waiting on this specific message with 396.Fn lwkt_domsg . 397.Pp 398As is the case with putport handler, the replyport handler can also be 399overridden. 400You override the default replyport handler by using the 401.Fn lwkt_initport_replyonly 402or the 403.Fn lwkt_initport_replyonly_null 404port initializers, or by manipulating the mp_replyport handler pointer directly 405on the 406.Vt lwkt_port 407structure. 408.Pp 409The sent message structure is reused for replies. 410When a message is replied to, the error response is written on the message 411which is subsequently sent to the reply port. 412.Sh FILES 413The LWKT msgport implementation resides in 414.Pa sys/kern/lwkt_msgport.c . 415.Sh EXAMPLES 416.Bd -literal 417/* 418 * Example 1: per CPU threads. 419 * 420 */ 421 422#include <sys/thread.h> 423#include <sys/msgport.h> 424#include <sys/msgport2.h> 425 426static void my_service_loop(void *dummy); 427lwkt_port_t my_service_portfn(int cpu); 428void my_service_sendmsg(lwkt_msg_t lmsg, int cpu); 429int my_service_domsg(lwkt_msg_t lmsg, int cpu); 430 431/* Array of per-CPU target ports */ 432struct lwkt_port *my_service_ports[MAXCPU]; 433 434/* 435 * Create per-cpu threads for handling msg processing. Remember that 436 * built-in lwkt ports are automatically initialized to type 'thread' 437 * so we don't need to initialize them explicitly. 438 */ 439static void 440my_per_cpu_service_init(void) 441{ 442 int i; 443 thread_t td; 444 445 for (i = 0; i < ncpus; ++i) { 446 lwkt_create(my_service_loop, NULL, &td, 447 NULL, 0, i, "myservice_cpu %d", i); 448 my_service_ports[i] = &td->td_msgport; 449 } 450} 451 452/* 453 * This is the routine executed by the service threads on each CPU. 454 */ 455static void 456my_service_loop(void *dummy __unused) 457{ 458 lwkt_msg_t msg; 459 thread_t td = curthread; 460 int cpu = curthread->td_gd->gd_cpuid; 461 462 while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 463 /* Do some work in the receiver thread context. */ 464 kprintf("Received message on CPU %d.\en", cpu); 465 466 /* And finally reply to the message. */ 467 lwkt_replymsg(msg, 0); 468 } 469} 470 471/* 472 * Given a CPU id, return our respective service port. 473 */ 474__inline lwkt_port_t 475my_service_portfn(int cpu) 476{ 477 return my_service_ports[cpu]; 478} 479 480/* 481 * Send an asynchronous message to the service thread on a specific CPU. 482 */ 483void 484my_service_sendmsg(lwkt_msg_t lmsg, int cpu) 485{ 486 KKASSERT(cpu < ncpus); 487 lwkt_sendmsg(my_service_portfn(cpu), lmsg); 488} 489 490/* 491 * Send a synchronous message to the service thread on a specific CPU. 492 */ 493int 494my_service_domsg(lwkt_msg_t lmsg, int cpu) 495{ 496 KKASSERT(cpu < ncpus); 497 return lwkt_domsg(my_service_portfn(cpu), lmsg, 0); 498} 499 500/* 501 * Example use case. Initialize the service threads and send each one a 502 * message. 503 */ 504static void 505mod_load(void) 506{ 507 lwkt_msg lmsg; 508 lwkt_port_t builtin_port = &curthread->td_msgport; 509 int i; 510 511 my_per_cpu_service_init(); 512 for (i=0; i<ncpus; ++i) { 513 kprintf("Sending msg to CPU %d.\en", i); 514 lwkt_initmsg(&lmsg, builtin_port, 0); 515 my_service_domsg(&lmsg, i); 516 } 517} 518 519/* 520 * Example 2: Dynamic allocated message passing with automatic free. 521 * 522 * This scenario is used when resources need to be freed after the 523 * message has been replied to. Features: 524 * - An argument is passed within the message. 525 * - Messages are allocated with kmalloc(). Replying to the message 526 * kfree()s it. 527 */ 528 529#include <sys/thread.h> 530#include <sys/msgport.h> 531#include <sys/msgport2.h> 532 533void my_service_queue(void *arg); 534 535lwkt_port my_autofree_rport; 536lwkt_port_t my_service_port; 537 538/* 539 * Use this function to send messages with a void * argument to our 540 * service thread. 541 */ 542void 543my_service_queue(void *arg) 544{ 545 lwkt_msg_t msg; 546 547 msg = kmalloc(sizeof(*msg), M_TEMP, M_WAITOK); 548 549 /* Set reply port to autofree. */ 550 lwkt_initmsg(msg, &my_autofree_rport, 0); 551 552 /* Attach the argument to the message. */ 553 msg->u.ms_resultp = arg; 554 555 /* Send it. */ 556 lwkt_sendmsg(my_service_port, msg); 557} 558 559/* 560 * This is the routine executed by our service thread. 561 */ 562static void 563my_service_loop(void *dummy __unused) 564{ 565 lwkt_msg_t msg; 566 thread_t td = curthread; 567 568 while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 569 /* 570 * Do some work in the receiver thread context. In this 571 * example, the sender wrote his name in the argument he 572 * sent us. We print it here. 573 */ 574 char *arg = msg->u.ms_resultp; 575 kprintf("%s: Hi %s! Got your msg.\en", curthread->td_comm, 576 arg); 577 578 /* And finally reply to the message. */ 579 lwkt_replymsg(msg, 0); 580 } 581} 582 583static void 584my_autofree_reply(lwkt_port_t port, lwkt_msg_t msg) 585{ 586 kfree(msg->u.ms_resultp, M_TEMP); 587 kfree(msg, M_TEMP); 588} 589 590static void 591my_service_init(void) 592{ 593 thread_t tdp; 594 595 /* Initialize our auto free reply port. */ 596 lwkt_initport_replyonly(&my_autofree_rport, my_autofree_reply); 597 598 /* Create our service thread on CPU 0. */ 599 lwkt_create(my_service_loop, NULL, &tdp, NULL, 0, 0, "myservice"); 600 my_service_port = &tdp->td_msgport; 601} 602 603/* 604 * Example use case. Initialize the service and send the current thread 605 * name to the service thread. 606 */ 607static void 608mod_load(void) 609{ 610 void *arg; 611 int len; 612 613 my_service_init(); 614 len = strlen(curthread->td_comm); 615 arg = kmalloc(len + 1, M_TEMP, M_WAITOK); 616 bcopy(curthread->td_comm, arg, len + 1); 617 kprintf("%s: Sending message.\en", curthread->td_comm); 618 my_service_queue(arg); 619} 620.Ed 621.Sh SEE ALSO 622.Xr serializer 9 , 623.Xr sleep 9 , 624.Xr spinlock 9 625.Sh HISTORY 626The LWKT msgport interface first appeared in 627.Dx 1.0 . 628.Sh AUTHORS 629.An -nosplit 630The 631.Nm msgport 632message passing interface implementation was written by 633.An Matthew Dillon . 634This manual page was written by 635.An Nuno Antunes . 636