| Commit | Line | Data |
|---|---|---|
| 94a4cc0b NA |
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 | |
| c6e8b6c1 SW |
103 | Light weight kernel threads in |
| 104 | .Dx | |
| 105 | may use a message passing interface to communicate with each other. | |
| 94a4cc0b NA |
106 | Messages are sent to message ports. |
| 107 | All light weight kernel threads have a built-in message port, but you may create | |
| 108 | additional ports if necessary. | |
| 109 | The following types of message ports are available: | |
| 110 | .Bl -bullet | |
| 111 | .It | |
| 112 | thread ports | |
| 113 | .It | |
| 114 | spin ports | |
| 115 | .It | |
| 116 | serializer ports | |
| 117 | .El | |
| 118 | .Pp | |
| 119 | Ports of type 'thread' are owned by a single light weight kernel thread. | |
| 120 | When a message is sent to a port of type 'thread', only the owner of that port | |
| 121 | is allowed to retrieve the message from it. | |
| 122 | When a message is sent to a port of type 'spin' or to a port of | |
| 123 | type 'serializer', multiple threads are allowed to check that port for new | |
| 124 | messages and compete to retrieve them. | |
| 125 | You define the port type when you initialize the port. | |
| 126 | By default, the built-in port of every light weight kernel thread is | |
| 127 | automatically initialized to type 'thread'. | |
| 128 | .Pp | |
| 129 | When a message is sent, the receiver should normally send back a reply. | |
| 130 | The reply is sent to the reply port that is registered on the original message. | |
| 131 | Messages can be replied to synchronously or asynchronously. | |
| 132 | The sender may request a synchronous or asynchronous reply to the message, | |
| 133 | however the target port will ultimately decide how the message will be treated. | |
| 134 | .Sh MESSAGE FUNCTIONS | |
| 135 | Messages must be initialized before being used. | |
| 136 | The | |
| 137 | .Fn lwkt_initmsg | |
| 138 | function initializes a message. | |
| 139 | The | |
| 140 | .Fa rport | |
| 141 | argument identifies the reply port which will be used for asynchronous replies. | |
| 142 | The | |
| 143 | .Fa flags | |
| 144 | argument sets any required flags for this message. | |
| 145 | Flags passed this way will simply be or'ed to any already existing flags on the | |
| 146 | message. | |
| 147 | .Pp | |
| 148 | The | |
| 149 | .Fn lwkt_initmsg_abortable | |
| 150 | function is similar to | |
| 151 | .Fn lwkt_initmsg | |
| 152 | but it takes an additional parameter | |
| 153 | .Fa abortfn | |
| 154 | which defines the abort function for this message. | |
| 155 | .Pp | |
| 156 | The | |
| 157 | .Fn lwkt_sendmsg | |
| 158 | function requests an asynchronous reply, sends the message and returns | |
| 159 | immediately. | |
| 160 | Under normal circumstances, users of this function may always expect the reply | |
| 161 | to be queued to the reply port registered on the message. | |
| 162 | The | |
| 163 | .Fa port | |
| 164 | argument defines the target port to which the | |
| 165 | .Fa msg | |
| 166 | message will be sent to. | |
| 167 | .Pp | |
| 168 | The | |
| 169 | .Fn lwkt_domsg | |
| 170 | function requests a synchronous reply, sends the message and does not return | |
| 171 | until the message has been replied to. | |
| 172 | If the target port supports synchronous reply, this function will return that | |
| 173 | reply immediately. | |
| 174 | If not, and this is the most common case, this function will block and wait for the | |
| 175 | reply to arrive and then return it. | |
| 176 | The | |
| 177 | .Fa port | |
| 178 | argument defines the target port to which the | |
| 179 | .Fa msg | |
| 180 | message will be sent to. | |
| 181 | .Pp | |
| 182 | The | |
| 183 | .Fn lwkt_replymsg | |
| 184 | function replies to a message that was processed asynchronously by the target | |
| 185 | port. | |
| 186 | This function is used by the thread on the receiving side. | |
| 187 | The | |
| 188 | .Fa msg | |
| 189 | argument is the message being replied to and the | |
| 190 | .Fa error | |
| 191 | argument is the actual response to send back. | |
| 192 | .Pp | |
| 193 | The | |
| 194 | .Fn lwkt_forwardmsg | |
| 195 | simply forwards a message to another port. | |
| 196 | The | |
| 197 | .Fa port | |
| 198 | argument defines the target port to which the | |
| 199 | .Fa msg | |
| 200 | message will be sent to. | |
| 201 | .Pp | |
| 202 | If a message has been initialized as abortable, you can use the | |
| 203 | .Fn lwkt_abortmsg | |
| 204 | function to try to abort it. | |
| 205 | The | |
| 206 | .Fa abortfn | |
| 207 | passed upon the initialisation with | |
| 208 | .Fn lwkt_initmsg_abortable | |
| 209 | will be called by this function. | |
| 210 | .Pp | |
| 211 | The | |
| 212 | .Fn lwkt_dropmsg | |
| 213 | will dequeue the specified message from the target port it was sent to and makes | |
| 214 | it look like it was never sent. | |
| 215 | .Sh PORT FUNCTIONS | |
| 216 | The | |
| 217 | .Fn lwkt_initport_thread | |
| 218 | initializes the specified | |
| 219 | .Fa port | |
| 220 | with the default 'thread' port type handlers. | |
| 221 | The | |
| 222 | .Fa td | |
| 223 | argument defines the owner thread of the port and only that thread is allowed to | |
| 224 | receive messages on it. | |
| 225 | .Pp | |
| 226 | The | |
| 227 | .Fn lwkt_initport_spin | |
| 228 | initializes the specified | |
| 229 | .Fa port | |
| 230 | with the default 'spin' port type handlers. | |
| 231 | It will also initialize the embedded spinlock within the | |
| 232 | lwkt_port structure which will protect subsequent port access. | |
| 233 | .Pp | |
| 234 | The | |
| 235 | .Fn lwkt_initport_serialize | |
| 236 | function initializes the specified | |
| 237 | .Fa port | |
| 238 | with the default 'serializer' port type handlers. | |
| 239 | The subsequent port access will be protected by the passed | |
| 240 | .Fa slz | |
| 241 | serializer lock. | |
| 242 | .Pp | |
| 243 | The | |
| 244 | .Fn lwkt_getport | |
| 245 | function checks the specified | |
| 246 | .Fa port | |
| 247 | for available messages, dequeues the first one and returns it. | |
| 248 | If no messages are available then | |
| 249 | .Dv NULL | |
| 250 | is returned instead. | |
| 251 | This function is used by threads on the receiving side. | |
| 252 | .Pp | |
| 253 | The | |
| 254 | .Fn lwkt_waitport | |
| 255 | function checks the specified | |
| 256 | .Fa port | |
| 257 | for available messages, dequeues the first one and returns it. | |
| 258 | If no messages are available then the caller thread will sleep until a message | |
| 259 | arrives on the specified port. | |
| 260 | The | |
| 261 | .Fa flags | |
| 262 | argument defines the flags used for the sleep. | |
| 263 | This function is used by threads on the receiving side. | |
| 264 | .Sh SPECIAL PORT INITIALIZERS | |
| 265 | The | |
| 266 | .Fn lwkt_initport_replyonly | |
| 267 | function initializes a | |
| 268 | .Fa port | |
| 269 | which is used only as reply port and may have a custom reply port handler. | |
| 270 | The reply port handler is specified with the | |
| 271 | .Fa rportfn | |
| 272 | argument. | |
| 273 | All the other handlers will panic the system if they are called. | |
| 274 | This initializer is normally used on ports for freeing resources after the | |
| 275 | messages have fulfilled their purpose. | |
| 276 | .Pp | |
| 277 | The | |
| 278 | .Fn lwkt_initport_replyonly_null | |
| 279 | function initializes a | |
| 280 | .Fa port | |
| 281 | which is used only as reply port. | |
| 282 | The reply port handler will simply mark the message as being done and will not | |
| 283 | attempt to queue it. | |
| 284 | All the other handlers will panic the system if they are called. | |
| 285 | .Pp | |
| 286 | The | |
| 287 | .Fn lwkt_initport_putonly | |
| 288 | function initializes a | |
| 289 | .Fa port | |
| 290 | which is used only as target port. | |
| 291 | The putport handler is specified with the | |
| 292 | .Fa pportfn | |
| 293 | argument. | |
| 294 | All the other handlers will panic the system if they are called. | |
| 295 | .Pp | |
| 296 | The | |
| 297 | .Fn lwkt_initport_panic | |
| 298 | function initializes a | |
| 299 | .Fa port | |
| 300 | which will panic the system if any of its handlers are called. | |
| 301 | This function is sometimes used to initialize a reply-only port which does not | |
| c6e8b6c1 SW |
302 | expect the messages to be replied to, e.g.\& when the messages should be |
| 303 | consumed by the receiving thread and never replied back. | |
| 94a4cc0b NA |
304 | .Sh INTERNAL MESSAGE FUNCTIONS |
| 305 | The following functions are used only by the infrastructure, you should not | |
| 306 | need to use them directly unless in very rare cases. | |
| 307 | .Pp | |
| 308 | The | |
| 309 | .Fn lwkt_beginmsg | |
| 310 | function simply calls the target port's putport handler. | |
| 311 | This function is only called by the | |
| 312 | .Fn lwkt_sendmsg | |
| 313 | and | |
| 314 | .Fn lwkt_replymsg | |
| 315 | functions. | |
| 316 | The putport handler returns | |
| 317 | .Er EASYNC | |
| 318 | for messages processed asynchronously or any other value for messages processed | |
| 319 | synchronously. | |
| 320 | That return value of the putport handler is propagated by this function. | |
| 321 | The | |
| 322 | .Fa port | |
| 323 | argument defines the target port to which the | |
| 324 | .Fa msg | |
| 325 | message will be sent to. | |
| 326 | .Pp | |
| 327 | The | |
| 328 | .Fn lwkt_waitmsg | |
| 329 | function puts the caller to sleep until the specified | |
| 330 | .Fa msg | |
| 331 | message has been replied to. | |
| 332 | The | |
| 333 | .Fa flags | |
| 334 | argument defines the flags used for the sleep. | |
| 335 | .Sh FILES | |
| 336 | The 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 | ||
| 349 | static void my_service_loop(void *dummy); | |
| 350 | lwkt_port_t my_service_portfn(int cpu); | |
| 351 | void my_service_sendmsg(lwkt_msg_t lmsg, int cpu); | |
| 352 | int my_service_domsg(lwkt_msg_t lmsg, int cpu); | |
| 353 | ||
| 354 | /* Array of per-CPU target ports */ | |
| 355 | struct 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 | */ | |
| 362 | static void | |
| 363 | my_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 | */ | |
| 378 | static void | |
| 379 | my_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 | |
| 398 | my_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 | */ | |
| 406 | void | |
| 407 | my_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 | */ | |
| 416 | int | |
| 417 | my_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 | */ | |
| 427 | static void | |
| 428 | mod_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 | ||
| 455 | void my_service_queue(void *arg); | |
| 456 | ||
| 457 | lwkt_port my_autofree_rport; | |
| 458 | lwkt_port_t my_service_port; | |
| 459 | ||
| 460 | /* | |
| 461 | * Use this function to send messages with a void * argument to our | |
| 462 | * service thread. | |
| 463 | */ | |
| 464 | void | |
| 465 | my_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 | */ | |
| 484 | static void | |
| 485 | my_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 | ||
| 504 | static void | |
| 505 | my_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 | ||
| 511 | static void | |
| 512 | my_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 | */ | |
| 528 | static void | |
| 529 | mod_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 | |
| 543 | All the default putport handlers (used when a message is sent) currently | |
| c6e8b6c1 | 544 | implement asynchronous putports only, i.e.\& all *_putport() handlers return |
| 94a4cc0b NA |
545 | .Er EASYNC . |
| 546 | You can still have synchronous putport handlers (which are run in the sender's | |
| 547 | context) but you have to implement the function yourself and then override the | |
| 548 | default. | |
| 549 | .Pp | |
| 550 | Port handler functions can be overridden with custom functions if required. | |
| 551 | You can override the default putport handler by either using the | |
| 552 | .Fn lwkt_initport_putonly | |
| 553 | initializer, or by manipulating the mp_putport handler pointer directly on the | |
| 554 | lwkt_port structure. | |
| 555 | .Pp | |
| 556 | There is one such case where the putport handler is overridden in | |
| c6e8b6c1 | 557 | .Pa sys/kern/netisr.c . |
| 94a4cc0b NA |
558 | In that case, the putport handler is overridden to detect a loopback message |
| 559 | (when the target port belongs to the sending thread). | |
| 560 | This special putport handler turns the sent message into a direct function call | |
| 561 | instead of queueing it to the port. | |
| 562 | .Pp | |
| 563 | The | |
| 564 | .Fn lwkt_replymsg | |
| c6e8b6c1 SW |
565 | function works differently depending on the original message request. |
| 566 | If the | |
| 94a4cc0b | 567 | message was originally an asynchronous request, the reply will be queued to the |
| c6e8b6c1 SW |
568 | sender's reply port. |
| 569 | If the message was originally a synchronous request, then | |
| 94a4cc0b NA |
570 | this function will just write the error response on the message and wake up the |
| 571 | waiter without queueing the message to the reply port. | |
| 572 | There is no need to queue in the synchronous request case because the original | |
| 573 | sender had blocked waiting on this specific message with | |
| 574 | .Fn lwkt_domsg . | |
| 575 | .Pp | |
| 576 | As is the case with putport handler, the replyport handler can also be | |
| 577 | overridden. | |
| 578 | You override the default replyport handler by using the | |
| 579 | .Fn lwkt_initport_replyonly | |
| 580 | or the | |
| 581 | .Fn lwkt_initport_replyonly_null | |
| 582 | port initializers, or by manipulating the mp_replyport handler pointer directly | |
| 583 | on the lwkt_port structure. | |
| 584 | .Pp | |
| 585 | The sent message structure is reused for replies. | |
| 586 | When a message is replied to, the error response is written on the message | |
| 587 | which is subsequently sent to the reply port. | |
| 588 | .Sh SEE ALSO | |
| 589 | .Xr serializer 9 , | |
| ecdcdf95 NA |
590 | .Xr spinlock 9 , |
| 591 | .Xr sleep 9 | |
| 94a4cc0b NA |
592 | .Sh HISTORY |
| 593 | The LWKT msgport interface first appeared in | |
| 594 | .Dx 1.0 . | |
| 595 | .Sh AUTHORS | |
| 596 | .An -nosplit | |
| 597 | The | |
| 598 | .Nm msgport | |
| 599 | message passing interface implementation was written by | |
| 600 | .An Matthew Dillon . | |
| 601 | This manual page was written by | |
| 602 | .An Nuno Antunes . |