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 August 12, 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" 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 'thread' are owned by a single light weight kernel thread. 120When a message is sent to a port of type 'thread', only the owner of that port 121is allowed to retrieve the message from it. 122When a message is sent to a port of type 'spin' or to a port of 123type 'serializer', multiple threads are allowed to check that port for new 124messages and compete to retrieve them. 125You define the port type when you initialize the port. 126By default, the built-in port of every light weight kernel thread is 127automatically initialized to type 'thread'. 128.Pp 129When a message is sent, the receiver should normally send back a reply. 130The reply is sent to the reply port that is registered on the original message. 131Messages can be replied to synchronously or asynchronously. 132The sender may request a synchronous or asynchronous reply to the message, 133however the target port will ultimately decide how the message will be treated. 134.Sh MESSAGE FUNCTIONS 135Messages must be initialized before being used. 136The 137.Fn lwkt_initmsg 138function initializes a message. 139The 140.Fa rport 141argument identifies the reply port which will be used for asynchronous replies. 142The 143.Fa flags 144argument sets any required flags for this message. 145Flags passed this way will simply be or'ed to any already existing flags on the 146message. 147.Pp 148The 149.Fn lwkt_initmsg_abortable 150function is similar to 151.Fn lwkt_initmsg 152but it takes an additional parameter 153.Fa abortfn 154which defines the abort function for this message. 155.Pp 156The 157.Fn lwkt_sendmsg 158function requests an asynchronous reply, sends the message and returns 159immediately. 160Under normal circumstances, users of this function may always expect the reply 161to be queued to the reply port registered on the message. 162The 163.Fa port 164argument defines the target port to which the 165.Fa msg 166message will be sent to. 167.Pp 168The 169.Fn lwkt_domsg 170function requests a synchronous reply, sends the message and does not return 171until the message has been replied to. 172If the target port supports synchronous reply, this function will return that 173reply immediately. 174If not, and this is the most common case, this function will block and wait for the 175reply to arrive and then return it. 176The 177.Fa port 178argument defines the target port to which the 179.Fa msg 180message will be sent to. 181.Pp 182The 183.Fn lwkt_replymsg 184function replies to a message that was processed asynchronously by the target 185port. 186This function is used by the thread on the receiving side. 187The 188.Fa msg 189argument is the message being replied to and the 190.Fa error 191argument is the actual response to send back. 192.Pp 193The 194.Fn lwkt_forwardmsg 195simply forwards a message to another port. 196The 197.Fa port 198argument defines the target port to which the 199.Fa msg 200message will be sent to. 201.Pp 202If a message has been initialized as abortable, you can use the 203.Fn lwkt_abortmsg 204function to try to abort it. 205The 206.Fa abortfn 207passed upon the initialisation with 208.Fn lwkt_initmsg_abortable 209will be called by this function. 210.Pp 211The 212.Fn lwkt_dropmsg 213will dequeue the specified message from the target port it was sent to and makes 214it look like it was never sent. 215.Sh PORT FUNCTIONS 216The 217.Fn lwkt_initport_thread 218initializes the specified 219.Fa port 220with the default 'thread' port type handlers. 221The 222.Fa td 223argument defines the owner thread of the port and only that thread is allowed to 224receive messages on it. 225.Pp 226The 227.Fn lwkt_initport_spin 228initializes the specified 229.Fa port 230with the default 'spin' port type handlers. 231It will also initialize the embedded spinlock within the 232lwkt_port structure which will protect subsequent port access. 233.Pp 234The 235.Fn lwkt_initport_serialize 236function initializes the specified 237.Fa port 238with the default 'serializer' port type handlers. 239The subsequent port access will be protected by the passed 240.Fa slz 241serializer lock. 242.Pp 243The 244.Fn lwkt_getport 245function checks the specified 246.Fa port 247for available messages, dequeues the first one and returns it. 248If no messages are available then 249.Dv NULL 250is returned instead. 251This function is used by threads on the receiving side. 252.Pp 253The 254.Fn lwkt_waitport 255function checks the specified 256.Fa port 257for available messages, dequeues the first one and returns it. 258If no messages are available then the caller thread will sleep until a message 259arrives on the specified port. 260The 261.Fa flags 262argument defines the flags used for the sleep. 263This function is used by threads on the receiving side. 264.Sh SPECIAL PORT INITIALIZERS 265The 266.Fn lwkt_initport_replyonly 267function initializes a 268.Fa port 269which is used only as reply port and may have a custom reply port handler. 270The reply port handler is specified with the 271.Fa rportfn 272argument. 273All the other handlers will panic the system if they are called. 274This initializer is normally used on ports for freeing resources after the 275messages have fulfilled their purpose. 276.Pp 277The 278.Fn lwkt_initport_replyonly_null 279function initializes a 280.Fa port 281which is used only as reply port. 282The reply port handler will simply mark the message as being done and will not 283attempt to queue it. 284All the other handlers will panic the system if they are called. 285.Pp 286The 287.Fn lwkt_initport_putonly 288function initializes a 289.Fa port 290which is used only as target port. 291The putport handler is specified with the 292.Fa pportfn 293argument. 294All the other handlers will panic the system if they are called. 295.Pp 296The 297.Fn lwkt_initport_panic 298function initializes a 299.Fa port 300which will panic the system if any of its handlers are called. 301This function is sometimes used to initialize a reply-only port which does not 302expect the messages to be replied to, e.g.\& when the messages should be 303consumed by the receiving thread and never replied back. 304.Sh INTERNAL MESSAGE FUNCTIONS 305The following functions are used only by the infrastructure, you should not 306need to use them directly unless in very rare cases. 307.Pp 308The 309.Fn lwkt_beginmsg 310function simply calls the target port's putport handler. 311This function is only called by the 312.Fn lwkt_sendmsg 313and 314.Fn lwkt_replymsg 315functions. 316The putport handler returns 317.Er EASYNC 318for messages processed asynchronously or any other value for messages processed 319synchronously. 320That return value of the putport handler is propagated by this function. 321The 322.Fa port 323argument defines the target port to which the 324.Fa msg 325message will be sent to. 326.Pp 327The 328.Fn lwkt_waitmsg 329function puts the caller to sleep until the specified 330.Fa msg 331message has been replied to. 332The 333.Fa flags 334argument defines the flags used for the sleep. 335.Sh FILES 336The LWKT msgport implementation resides in 337.Pa sys/kern/lwkt_msgport.c . 338.Sh EXAMPLES 339.Bd -literal 340/* 341 * Example 1: per CPU threads. 342 * 343 */ 344 345#include <sys/thread.h> 346#include <sys/msgport.h> 347#include <sys/msgport2.h> 348 349static void my_service_loop(void *dummy); 350lwkt_port_t my_service_portfn(int cpu); 351void my_service_sendmsg(lwkt_msg_t lmsg, int cpu); 352int my_service_domsg(lwkt_msg_t lmsg, int cpu); 353 354/* Array of per-CPU target ports */ 355struct lwkt_port *my_service_ports[MAXCPU]; 356 357/* 358 * Create per-cpu threads for handling msg processing. Remember that built-in 359 * lwkt ports are automatically initialized to type 'thread' so we don't need 360 * to initialize them explicitly. 361 */ 362static void 363my_per_cpu_service_init(void) 364{ 365 int i; 366 thread_t td; 367 368 for (i = 0; i < ncpus; ++i) { 369 lwkt_create(my_service_loop, NULL, &td, 370 NULL, 0, i, "myservice_cpu %d", i); 371 my_service_ports[i] = &td->td_msgport; 372 } 373} 374 375/* 376 * This is the routine executed by the service threads on each CPU. 377 */ 378static void 379my_service_loop(void *dummy __unused) 380{ 381 lwkt_msg_t msg; 382 thread_t td = curthread; 383 int cpu = curthread->td_gd->gd_cpuid; 384 385 while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 386 /* Do some work in the receiver thread context. */ 387 kprintf("Received message on CPU %d.\en", cpu); 388 389 /* And finally reply to the message. */ 390 lwkt_replymsg(msg, 0); 391 } 392} 393 394/* 395 * Given a CPU id, return our respective service port. 396 */ 397__inline lwkt_port_t 398my_service_portfn(int cpu) 399{ 400 return my_service_ports[cpu]; 401} 402 403/* 404 * Send an asynchronous message to the service thread on a specific CPU. 405 */ 406void 407my_service_sendmsg(lwkt_msg_t lmsg, int cpu) 408{ 409 KKASSERT(cpu < ncpus); 410 lwkt_sendmsg(my_service_portfn(cpu), lmsg); 411} 412 413/* 414 * Send a synchronous message to the service thread on a specific CPU. 415 */ 416int 417my_service_domsg(lwkt_msg_t lmsg, int cpu) 418{ 419 KKASSERT(cpu < ncpus); 420 return lwkt_domsg(my_service_portfn(cpu), lmsg, 0); 421} 422 423/* 424 * Example use case. Initialize the service threads and send each one a 425 * message. 426 */ 427static void 428mod_load(void) 429{ 430 lwkt_msg lmsg; 431 lwkt_port_t builtin_port = &curthread->td_msgport; 432 int i; 433 434 my_per_cpu_service_init(); 435 for (i=0; i<ncpus; ++i) { 436 kprintf("Sending msg to CPU %d.\en", i); 437 lwkt_initmsg(&lmsg, builtin_port, 0); 438 my_service_domsg(&lmsg, i); 439 } 440} 441 442/* 443 * Example 2: Dynamic allocated message passing with automatic free. 444 * 445 * This scenario is used when resources need to be freed after the message 446 * has been replied to. Features: 447 * - An argument is passed within the message. 448 * - Messages are allocated with kmalloc(). Replying to the msg, kfree()s it. 449 */ 450 451#include <sys/thread.h> 452#include <sys/msgport.h> 453#include <sys/msgport2.h> 454 455void my_service_queue(void *arg); 456 457lwkt_port my_autofree_rport; 458lwkt_port_t my_service_port; 459 460/* 461 * Use this function to send messages with a void * argument to our 462 * service thread. 463 */ 464void 465my_service_queue(void *arg) 466{ 467 lwkt_msg_t msg; 468 469 msg = kmalloc(sizeof(*msg), M_TEMP, M_WAITOK); 470 471 /* Set reply port to autofree. */ 472 lwkt_initmsg(msg, &my_autofree_rport, 0); 473 474 /* Attach the argument to the message. */ 475 msg->u.ms_resultp = arg; 476 477 /* Send it. */ 478 lwkt_sendmsg(my_service_port, msg); 479} 480 481/* 482 * This is the routine executed by our service thread. 483 */ 484static void 485my_service_loop(void *dummy __unused) 486{ 487 lwkt_msg_t msg; 488 thread_t td = curthread; 489 490 while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 491 /* 492 * Do some work in the receiver thread context. In this 493 * example, the sender wrote his name in the argument he 494 * sent us. We print it here. 495 */ 496 char *arg = msg->u.ms_resultp; 497 kprintf("%s: Hi %s! Got your msg.\en", curthread->td_comm, arg); 498 499 /* And finally reply to the message. */ 500 lwkt_replymsg(msg, 0); 501 } 502} 503 504static void 505my_autofree_reply(lwkt_port_t port, lwkt_msg_t msg) 506{ 507 kfree(msg->u.ms_resultp, M_TEMP); 508 kfree(msg, M_TEMP); 509} 510 511static void 512my_service_init(void) 513{ 514 thread_t tdp; 515 516 /* Initialize our auto free reply port. */ 517 lwkt_initport_replyonly(&my_autofree_rport, my_autofree_reply); 518 519 /* Create our service thread on CPU 0. */ 520 lwkt_create(my_service_loop, NULL, &tdp, NULL, 0, 0, "myservice"); 521 my_service_port = &tdp->td_msgport; 522} 523 524/* 525 * Example use case. Initialize the service and send the current thread name 526 * to the service thread. 527 */ 528static void 529mod_load(void) 530{ 531 void *arg; 532 int len; 533 534 my_service_init(); 535 len = strlen(curthread->td_comm); 536 arg = kmalloc(len + 1, M_TEMP, M_WAITOK); 537 bcopy(curthread->td_comm, arg, len + 1); 538 kprintf("%s: Sending message.\en", curthread->td_comm); 539 my_service_queue(arg); 540} 541.Ed 542.Sh NOTES 543All the default putport handlers (used when a message is sent) currently 544implement asynchronous putports only, i.e.\& all *_putport() handlers return 545.Er EASYNC . 546You can still have synchronous putport handlers (which are run in the sender's 547context) but you have to implement the function yourself and then override the 548default. 549.Pp 550Port handler functions can be overridden with custom functions if required. 551You can override the default putport handler by either using the 552.Fn lwkt_initport_putonly 553initializer, or by manipulating the mp_putport handler pointer directly on the 554lwkt_port structure. 555.Pp 556There is one such case where the putport handler is overridden in 557.Pa sys/kern/netisr.c . 558In that case, the putport handler is overridden to detect a loopback message 559(when the target port belongs to the sending thread). 560This special putport handler turns the sent message into a direct function call 561instead of queueing it to the port. 562.Pp 563The 564.Fn lwkt_replymsg 565function works differently depending on the original message request. 566If the 567message was originally an asynchronous request, the reply will be queued to the 568sender's reply port. 569If the message was originally a synchronous request, then 570this function will just write the error response on the message and wake up the 571waiter without queueing the message to the reply port. 572There is no need to queue in the synchronous request case because the original 573sender had blocked waiting on this specific message with 574.Fn lwkt_domsg . 575.Pp 576As is the case with putport handler, the replyport handler can also be 577overridden. 578You override the default replyport handler by using the 579.Fn lwkt_initport_replyonly 580or the 581.Fn lwkt_initport_replyonly_null 582port initializers, or by manipulating the mp_replyport handler pointer directly 583on the lwkt_port structure. 584.Pp 585The sent message structure is reused for replies. 586When a message is replied to, the error response is written on the message 587which is subsequently sent to the reply port. 588.Sh SEE ALSO 589.Xr serializer 9 , 590.Xr sleep 9 , 591.Xr spinlock 9 592.Sh HISTORY 593The LWKT msgport interface first appeared in 594.Dx 1.0 . 595.Sh AUTHORS 596.An -nosplit 597The 598.Nm msgport 599message passing interface implementation was written by 600.An Matthew Dillon . 601This manual page was written by 602.An Nuno Antunes . 603