msgport.9: Add cross reference to sleep(9).
[dragonfly.git] / share / man / man9 / msgport.9
CommitLineData
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
103Light weight kernel threads in
104.Dx
105may use a message passing interface to communicate with each other.
94a4cc0b
NA
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
c6e8b6c1
SW
302expect the messages to be replied to, e.g.\& when the messages should be
303consumed by the receiving thread and never replied back.
94a4cc0b
NA
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
c6e8b6c1 544implement asynchronous putports only, i.e.\& all *_putport() handlers return
94a4cc0b
NA
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
c6e8b6c1 557.Pa sys/kern/netisr.c .
94a4cc0b
NA
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
c6e8b6c1
SW
565function works differently depending on the original message request.
566If the
94a4cc0b 567message was originally an asynchronous request, the reply will be queued to the
c6e8b6c1
SW
568sender's reply port.
569If the message was originally a synchronous request, then
94a4cc0b
NA
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 ,
ecdcdf95
NA
590.Xr spinlock 9 ,
591.Xr sleep 9
94a4cc0b
NA
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 .