xref: /dflybsd-src/share/man/man9/msgport.9 (revision 1f6708b6cc9f94c74fd97cbd39c8b7c44d817da3)
194a4cc0bSNuno Antunes.\"
2*1f6708b6SNuno Antunes.\" Copyright (c) 2012-2014 The DragonFly Project.  All rights reserved.
394a4cc0bSNuno Antunes.\"
494a4cc0bSNuno Antunes.\" This code is derived from software contributed to The DragonFly Project
594a4cc0bSNuno Antunes.\" by Nuno Antunes <nuno.antunes@gmail.com>.
694a4cc0bSNuno Antunes.\"
794a4cc0bSNuno Antunes.\" Redistribution and use in source and binary forms, with or without
894a4cc0bSNuno Antunes.\" modification, are permitted provided that the following conditions
994a4cc0bSNuno Antunes.\" are met:
1094a4cc0bSNuno Antunes.\"
1194a4cc0bSNuno Antunes.\" 1. Redistributions of source code must retain the above copyright
1294a4cc0bSNuno Antunes.\"    notice, this list of conditions and the following disclaimer.
1394a4cc0bSNuno Antunes.\" 2. Redistributions in binary form must reproduce the above copyright
1494a4cc0bSNuno Antunes.\"    notice, this list of conditions and the following disclaimer in
1594a4cc0bSNuno Antunes.\"    the documentation and/or other materials provided with the
1694a4cc0bSNuno Antunes.\"    distribution.
1794a4cc0bSNuno Antunes.\" 3. Neither the name of The DragonFly Project nor the names of its
1894a4cc0bSNuno Antunes.\"    contributors may be used to endorse or promote products derived
1994a4cc0bSNuno Antunes.\"    from this software without specific, prior written permission.
2094a4cc0bSNuno Antunes.\"
2194a4cc0bSNuno Antunes.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2294a4cc0bSNuno Antunes.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2394a4cc0bSNuno Antunes.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2494a4cc0bSNuno Antunes.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
2594a4cc0bSNuno Antunes.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2694a4cc0bSNuno Antunes.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2794a4cc0bSNuno Antunes.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2894a4cc0bSNuno Antunes.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2994a4cc0bSNuno Antunes.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3094a4cc0bSNuno Antunes.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3194a4cc0bSNuno Antunes.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3294a4cc0bSNuno Antunes.\" SUCH DAMAGE.
3394a4cc0bSNuno Antunes.\"
34*1f6708b6SNuno Antunes.Dd July 16, 2014
3594a4cc0bSNuno Antunes.Dt MSGPORT 9
3694a4cc0bSNuno Antunes.Os
3794a4cc0bSNuno Antunes.Sh NAME
3894a4cc0bSNuno Antunes.Nm lwkt_initport_thread ,
3994a4cc0bSNuno Antunes.Nm lwkt_initport_spin ,
4094a4cc0bSNuno Antunes.Nm lwkt_initport_serialize ,
4194a4cc0bSNuno Antunes.Nm lwkt_initport_panic ,
4294a4cc0bSNuno Antunes.Nm lwkt_initport_replyonly_null ,
4394a4cc0bSNuno Antunes.Nm lwkt_initport_replyonly ,
4494a4cc0bSNuno Antunes.Nm lwkt_initport_putonly ,
4594a4cc0bSNuno Antunes.Nm lwkt_sendmsg ,
4694a4cc0bSNuno Antunes.Nm lwkt_domsg ,
4794a4cc0bSNuno Antunes.Nm lwkt_forwardmsg ,
4894a4cc0bSNuno Antunes.Nm lwkt_abortmsg ,
4994a4cc0bSNuno Antunes.Nm lwkt_initmsg ,
5094a4cc0bSNuno Antunes.Nm lwkt_initmsg_abortable ,
5194a4cc0bSNuno Antunes.Nm lwkt_beginmsg ,
5294a4cc0bSNuno Antunes.Nm lwkt_replymsg ,
5394a4cc0bSNuno Antunes.Nm lwkt_getport ,
5494a4cc0bSNuno Antunes.Nm lwkt_waitport ,
5594a4cc0bSNuno Antunes.Nm lwkt_waitmsg ,
5694a4cc0bSNuno Antunes.Nm lwkt_checkmsg ,
5794a4cc0bSNuno Antunes.Nm lwkt_dropmsg
5894a4cc0bSNuno Antunes.Nd LWKT message passing interface
5994a4cc0bSNuno Antunes.Sh SYNOPSIS
6094a4cc0bSNuno Antunes.In sys/msgport.h
6194a4cc0bSNuno Antunes.Ft void
6294a4cc0bSNuno Antunes.Fn lwkt_initport_thread "lwkt_port_t port" "struct thread *td"
6394a4cc0bSNuno Antunes.Ft void
64*1f6708b6SNuno Antunes.Fn lwkt_initport_spin "lwkt_port_t port" "struct thread *td" "boolean_t fixed_cpuid"
6594a4cc0bSNuno Antunes.Ft void
6694a4cc0bSNuno Antunes.Fn lwkt_initport_serialize "lwkt_port_t port" "struct lwkt_serialize *slz"
6794a4cc0bSNuno Antunes.Ft void
6894a4cc0bSNuno Antunes.Fn lwkt_initport_panic "lwkt_port_t port"
6994a4cc0bSNuno Antunes.Ft void
7094a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly_null "lwkt_port_t port"
7194a4cc0bSNuno Antunes.Ft void
7294a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly "lwkt_port_t port" "void (*rportfn)(lwkt_port_t, lwkt_msg_t)"
7394a4cc0bSNuno Antunes.Ft void
7494a4cc0bSNuno Antunes.Fn lwkt_initport_putonly "lwkt_port_t port" "int (*pportfn)(lwkt_port_t, lwkt_msg_t)"
7594a4cc0bSNuno Antunes.Ft void
7694a4cc0bSNuno Antunes.Fn lwkt_sendmsg "lwkt_port_t port" "lwkt_msg_t msg"
7794a4cc0bSNuno Antunes.Ft int
7894a4cc0bSNuno Antunes.Fn lwkt_domsg "lwkt_port_t port" "lwkt_msg_t msg" "int flags"
7994a4cc0bSNuno Antunes.Ft int
8094a4cc0bSNuno Antunes.Fn lwkt_forwardmsg "lwkt_port_t port" "lwkt_msg_t msg"
8194a4cc0bSNuno Antunes.Ft void
8294a4cc0bSNuno Antunes.Fn lwkt_abortmsg "lwkt_msg_t msg"
8394a4cc0bSNuno Antunes.In sys/msgport2.h
8494a4cc0bSNuno Antunes.Ft void
8594a4cc0bSNuno Antunes.Fn lwkt_initmsg "lwkt_msg_t msg" "lwkt_port_t rport" "int flags"
8694a4cc0bSNuno Antunes.Ft void
8794a4cc0bSNuno Antunes.Fn lwkt_initmsg_abortable "lwkt_msg_t msg" "lwkt_port_t rport" "int flags" "void (*abortfn)(lwkt_msg_t)"
8894a4cc0bSNuno Antunes.Ft int
8994a4cc0bSNuno Antunes.Fn lwkt_beginmsg "lwkt_port_t port" "lwkt_msg_t msg"
9094a4cc0bSNuno Antunes.Ft void
9194a4cc0bSNuno Antunes.Fn lwkt_replymsg "lwkt_msg_t msg" "int error"
9294a4cc0bSNuno Antunes.Ft void *
9394a4cc0bSNuno Antunes.Fn lwkt_getport "lwkt_port_t port"
9494a4cc0bSNuno Antunes.Ft void *
9594a4cc0bSNuno Antunes.Fn lwkt_waitport "lwkt_port_t port" "int flags"
9694a4cc0bSNuno Antunes.Ft int
9794a4cc0bSNuno Antunes.Fn lwkt_waitmsg "lwkt_msg_t msg" "int flags"
9894a4cc0bSNuno Antunes.Ft int
9994a4cc0bSNuno Antunes.Fn lwkt_checkmsg "lwkt_msg_t msg"
100e53bd087SSascha Wildner.Ft int
10194a4cc0bSNuno Antunes.Fn lwkt_dropmsg "lwkt_msg_t msg"
10294a4cc0bSNuno Antunes.Sh DESCRIPTION
103c6e8b6c1SSascha WildnerLight weight kernel threads in
104c6e8b6c1SSascha Wildner.Dx
105c6e8b6c1SSascha Wildnermay use a message passing interface to communicate with each other.
10694a4cc0bSNuno AntunesMessages are sent to message ports.
10794a4cc0bSNuno AntunesAll light weight kernel threads have a built-in message port, but you may create
10894a4cc0bSNuno Antunesadditional ports if necessary.
10994a4cc0bSNuno AntunesThe following types of message ports are available:
11094a4cc0bSNuno Antunes.Bl -bullet
11194a4cc0bSNuno Antunes.It
11294a4cc0bSNuno Antunesthread ports
11394a4cc0bSNuno Antunes.It
11494a4cc0bSNuno Antunesspin ports
11594a4cc0bSNuno Antunes.It
11694a4cc0bSNuno Antunesserializer ports
11794a4cc0bSNuno Antunes.El
11894a4cc0bSNuno Antunes.Pp
1190d6ab30eSSascha WildnerPorts of type
1200d6ab30eSSascha Wildner.Sq thread
1210d6ab30eSSascha Wildnerare owned by a single light weight kernel thread.
1220d6ab30eSSascha WildnerWhen a message is sent to a port of type
1230d6ab30eSSascha Wildner.Sq thread ,
1240d6ab30eSSascha Wildneronly the owner of that port is allowed to retrieve the message from it.
1250d6ab30eSSascha WildnerWhen a message is sent to a port of type
1260d6ab30eSSascha Wildner.Sq spin
1270d6ab30eSSascha Wildneror to a port of type
1280d6ab30eSSascha Wildner.Sq serializer ,
1290d6ab30eSSascha Wildnermultiple threads are allowed to check that port for new
13094a4cc0bSNuno Antunesmessages and compete to retrieve them.
13194a4cc0bSNuno AntunesYou define the port type when you initialize the port.
13294a4cc0bSNuno AntunesBy default, the built-in port of every light weight kernel thread is
1330d6ab30eSSascha Wildnerautomatically initialized to type
1340d6ab30eSSascha Wildner.Sq thread .
13594a4cc0bSNuno Antunes.Pp
13694a4cc0bSNuno AntunesWhen a message is sent, the receiver should normally send back a reply.
13794a4cc0bSNuno AntunesThe reply is sent to the reply port that is registered on the original message.
13894a4cc0bSNuno AntunesMessages can be replied to synchronously or asynchronously.
13994a4cc0bSNuno AntunesThe sender may request a synchronous or asynchronous reply to the message,
14094a4cc0bSNuno Antuneshowever the target port will ultimately decide how the message will be treated.
14194a4cc0bSNuno Antunes.Sh MESSAGE FUNCTIONS
14294a4cc0bSNuno AntunesMessages must be initialized before being used.
14394a4cc0bSNuno AntunesThe
14494a4cc0bSNuno Antunes.Fn lwkt_initmsg
14594a4cc0bSNuno Antunesfunction initializes a message.
14694a4cc0bSNuno AntunesThe
14794a4cc0bSNuno Antunes.Fa rport
14894a4cc0bSNuno Antunesargument identifies the reply port which will be used for asynchronous replies.
14994a4cc0bSNuno AntunesThe
15094a4cc0bSNuno Antunes.Fa flags
15194a4cc0bSNuno Antunesargument sets any required flags for this message.
15294a4cc0bSNuno AntunesFlags passed this way will simply be or'ed to any already existing flags on the
15394a4cc0bSNuno Antunesmessage.
15494a4cc0bSNuno Antunes.Pp
15594a4cc0bSNuno AntunesThe
15694a4cc0bSNuno Antunes.Fn lwkt_initmsg_abortable
15794a4cc0bSNuno Antunesfunction is similar to
15894a4cc0bSNuno Antunes.Fn lwkt_initmsg
15994a4cc0bSNuno Antunesbut it takes an additional parameter
16094a4cc0bSNuno Antunes.Fa abortfn
16194a4cc0bSNuno Antuneswhich defines the abort function for this message.
16294a4cc0bSNuno Antunes.Pp
16394a4cc0bSNuno AntunesThe
16494a4cc0bSNuno Antunes.Fn lwkt_sendmsg
16594a4cc0bSNuno Antunesfunction requests an asynchronous reply, sends the message and returns
16694a4cc0bSNuno Antunesimmediately.
16794a4cc0bSNuno AntunesUnder normal circumstances, users of this function may always expect the reply
16894a4cc0bSNuno Antunesto be queued to the reply port registered on the message.
16994a4cc0bSNuno AntunesThe
17094a4cc0bSNuno Antunes.Fa port
17194a4cc0bSNuno Antunesargument defines the target port to which the
17294a4cc0bSNuno Antunes.Fa msg
1730d6ab30eSSascha Wildnermessage will be sent.
17494a4cc0bSNuno Antunes.Pp
17594a4cc0bSNuno AntunesThe
17694a4cc0bSNuno Antunes.Fn lwkt_domsg
17794a4cc0bSNuno Antunesfunction requests a synchronous reply, sends the message and does not return
17894a4cc0bSNuno Antunesuntil the message has been replied to.
17994a4cc0bSNuno AntunesIf the target port supports synchronous reply, this function will return that
18094a4cc0bSNuno Antunesreply immediately.
18194a4cc0bSNuno AntunesIf not, and this is the most common case, this function will block and wait for the
18294a4cc0bSNuno Antunesreply to arrive and then return it.
18394a4cc0bSNuno AntunesThe
18494a4cc0bSNuno Antunes.Fa port
18594a4cc0bSNuno Antunesargument defines the target port to which the
18694a4cc0bSNuno Antunes.Fa msg
1870d6ab30eSSascha Wildnermessage will be sent.
18894a4cc0bSNuno Antunes.Pp
18994a4cc0bSNuno AntunesThe
19094a4cc0bSNuno Antunes.Fn lwkt_replymsg
19194a4cc0bSNuno Antunesfunction replies to a message that was processed asynchronously by the target
19294a4cc0bSNuno Antunesport.
19394a4cc0bSNuno AntunesThis function is used by the thread on the receiving side.
19494a4cc0bSNuno AntunesThe
19594a4cc0bSNuno Antunes.Fa msg
19694a4cc0bSNuno Antunesargument is the message being replied to and the
19794a4cc0bSNuno Antunes.Fa error
19894a4cc0bSNuno Antunesargument is the actual response to send back.
19994a4cc0bSNuno Antunes.Pp
20094a4cc0bSNuno AntunesThe
20194a4cc0bSNuno Antunes.Fn lwkt_forwardmsg
20294a4cc0bSNuno Antunessimply forwards a message to another port.
20394a4cc0bSNuno AntunesThe
20494a4cc0bSNuno Antunes.Fa port
20594a4cc0bSNuno Antunesargument defines the target port to which the
20694a4cc0bSNuno Antunes.Fa msg
2070d6ab30eSSascha Wildnermessage will be sent.
20894a4cc0bSNuno Antunes.Pp
20994a4cc0bSNuno AntunesIf a message has been initialized as abortable, you can use the
21094a4cc0bSNuno Antunes.Fn lwkt_abortmsg
21194a4cc0bSNuno Antunesfunction to try to abort it.
21294a4cc0bSNuno AntunesThe
21394a4cc0bSNuno Antunes.Fa abortfn
21494a4cc0bSNuno Antunespassed upon the initialisation with
21594a4cc0bSNuno Antunes.Fn lwkt_initmsg_abortable
21694a4cc0bSNuno Antuneswill be called by this function.
21794a4cc0bSNuno Antunes.Pp
21894a4cc0bSNuno AntunesThe
21994a4cc0bSNuno Antunes.Fn lwkt_dropmsg
22094a4cc0bSNuno Antuneswill dequeue the specified message from the target port it was sent to and makes
22194a4cc0bSNuno Antunesit look like it was never sent.
222ee779b4aSNuno AntunesThis function can only be used by the thread that owns the target port.
22394a4cc0bSNuno Antunes.Sh PORT FUNCTIONS
22494a4cc0bSNuno AntunesThe
22594a4cc0bSNuno Antunes.Fn lwkt_initport_thread
22694a4cc0bSNuno Antunesinitializes the specified
22794a4cc0bSNuno Antunes.Fa port
2280d6ab30eSSascha Wildnerwith the default
2290d6ab30eSSascha Wildner.Sq thread
2300d6ab30eSSascha Wildnerport type handlers.
23194a4cc0bSNuno AntunesThe
23294a4cc0bSNuno Antunes.Fa td
23394a4cc0bSNuno Antunesargument defines the owner thread of the port and only that thread is allowed to
23494a4cc0bSNuno Antunesreceive messages on it.
23594a4cc0bSNuno Antunes.Pp
23694a4cc0bSNuno AntunesThe
23794a4cc0bSNuno Antunes.Fn lwkt_initport_spin
23894a4cc0bSNuno Antunesinitializes the specified
23994a4cc0bSNuno Antunes.Fa port
2400d6ab30eSSascha Wildnerwith the default
2410d6ab30eSSascha Wildner.Sq spin
2420d6ab30eSSascha Wildnerport type handlers.
243ee779b4aSNuno AntunesThe
244ee779b4aSNuno Antunes.Fa td
245ee779b4aSNuno Antunesargument defines the owner thread of the port, for cases where thread built-in
2460d6ab30eSSascha Wildnerports are initialized as
2470d6ab30eSSascha Wildner.Sq spin
2480d6ab30eSSascha Wildnerports.
249ee779b4aSNuno AntunesIf
250ee779b4aSNuno Antunes.Dv NULL
251ee779b4aSNuno Antunesis passed, then the port will not have a defined owner, so functions like
252ee779b4aSNuno Antunes.Fn lwkt_dropmsg
253ee779b4aSNuno Antuneswill not be available for this port.
254*1f6708b6SNuno AntunesIf we know that this
255*1f6708b6SNuno Antunes.Sq spin
256*1f6708b6SNuno Antunesport is accessed exclusively by threads on a single CPU, we can set the
257*1f6708b6SNuno Antunes.Fa fixed_cpuid
258*1f6708b6SNuno Antunesargument to true, which will prevent the occurrence of unnecessary IPIs trying
259*1f6708b6SNuno Antunesto wake up threads on other CPUs.
260ee779b4aSNuno AntunesThis function will also initialize the embedded spinlock within the
2610d6ab30eSSascha Wildner.Vt lwkt_port
2620d6ab30eSSascha Wildnerstructure which will protect subsequent port access.
26394a4cc0bSNuno Antunes.Pp
26494a4cc0bSNuno AntunesThe
26594a4cc0bSNuno Antunes.Fn lwkt_initport_serialize
26694a4cc0bSNuno Antunesfunction initializes the specified
26794a4cc0bSNuno Antunes.Fa port
2680d6ab30eSSascha Wildnerwith the default
2690d6ab30eSSascha Wildner.Sq serializer
2700d6ab30eSSascha Wildnerport type handlers.
27194a4cc0bSNuno AntunesThe subsequent port access will be protected by the passed
27294a4cc0bSNuno Antunes.Fa slz
27394a4cc0bSNuno Antunesserializer lock.
27494a4cc0bSNuno Antunes.Pp
27594a4cc0bSNuno AntunesThe
27694a4cc0bSNuno Antunes.Fn lwkt_getport
27794a4cc0bSNuno Antunesfunction checks the specified
27894a4cc0bSNuno Antunes.Fa port
27994a4cc0bSNuno Antunesfor available messages, dequeues the first one and returns it.
28094a4cc0bSNuno AntunesIf no messages are available then
28194a4cc0bSNuno Antunes.Dv NULL
28294a4cc0bSNuno Antunesis returned instead.
28394a4cc0bSNuno AntunesThis function is used by threads on the receiving side.
28494a4cc0bSNuno Antunes.Pp
28594a4cc0bSNuno AntunesThe
28694a4cc0bSNuno Antunes.Fn lwkt_waitport
28794a4cc0bSNuno Antunesfunction checks the specified
28894a4cc0bSNuno Antunes.Fa port
28994a4cc0bSNuno Antunesfor available messages, dequeues the first one and returns it.
29094a4cc0bSNuno AntunesIf no messages are available then the caller thread will sleep until a message
29194a4cc0bSNuno Antunesarrives on the specified port.
29294a4cc0bSNuno AntunesThe
29394a4cc0bSNuno Antunes.Fa flags
29494a4cc0bSNuno Antunesargument defines the flags used for the sleep.
29594a4cc0bSNuno AntunesThis function is used by threads on the receiving side.
29694a4cc0bSNuno Antunes.Sh SPECIAL PORT INITIALIZERS
29794a4cc0bSNuno AntunesThe
29894a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly
29994a4cc0bSNuno Antunesfunction initializes a
30094a4cc0bSNuno Antunes.Fa port
30194a4cc0bSNuno Antuneswhich is used only as reply port and may have a custom reply port handler.
30294a4cc0bSNuno AntunesThe reply port handler is specified with the
30394a4cc0bSNuno Antunes.Fa rportfn
30494a4cc0bSNuno Antunesargument.
30594a4cc0bSNuno AntunesAll the other handlers will panic the system if they are called.
30694a4cc0bSNuno AntunesThis initializer is normally used on ports for freeing resources after the
30794a4cc0bSNuno Antunesmessages have fulfilled their purpose.
30894a4cc0bSNuno Antunes.Pp
30994a4cc0bSNuno AntunesThe
31094a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly_null
31194a4cc0bSNuno Antunesfunction initializes a
31294a4cc0bSNuno Antunes.Fa port
31394a4cc0bSNuno Antuneswhich is used only as reply port.
31494a4cc0bSNuno AntunesThe reply port handler will simply mark the message as being done and will not
31594a4cc0bSNuno Antunesattempt to queue it.
31694a4cc0bSNuno AntunesAll the other handlers will panic the system if they are called.
31794a4cc0bSNuno Antunes.Pp
31894a4cc0bSNuno AntunesThe
31994a4cc0bSNuno Antunes.Fn lwkt_initport_putonly
32094a4cc0bSNuno Antunesfunction initializes a
32194a4cc0bSNuno Antunes.Fa port
32294a4cc0bSNuno Antuneswhich is used only as target port.
32394a4cc0bSNuno AntunesThe putport handler is specified with the
32494a4cc0bSNuno Antunes.Fa pportfn
32594a4cc0bSNuno Antunesargument.
32694a4cc0bSNuno AntunesAll the other handlers will panic the system if they are called.
32794a4cc0bSNuno Antunes.Pp
32894a4cc0bSNuno AntunesThe
32994a4cc0bSNuno Antunes.Fn lwkt_initport_panic
33094a4cc0bSNuno Antunesfunction initializes a
33194a4cc0bSNuno Antunes.Fa port
33294a4cc0bSNuno Antuneswhich will panic the system if any of its handlers are called.
33394a4cc0bSNuno AntunesThis function is sometimes used to initialize a reply-only port which does not
334c6e8b6c1SSascha Wildnerexpect the messages to be replied to, e.g.\& when the messages should be
335c6e8b6c1SSascha Wildnerconsumed by the receiving thread and never replied back.
33694a4cc0bSNuno Antunes.Sh INTERNAL MESSAGE FUNCTIONS
33794a4cc0bSNuno AntunesThe following functions are used only by the infrastructure, you should not
33894a4cc0bSNuno Antunesneed to use them directly unless in very rare cases.
33994a4cc0bSNuno Antunes.Pp
34094a4cc0bSNuno AntunesThe
34194a4cc0bSNuno Antunes.Fn lwkt_beginmsg
34294a4cc0bSNuno Antunesfunction simply calls the target port's putport handler.
34394a4cc0bSNuno AntunesThis function is only called by the
34494a4cc0bSNuno Antunes.Fn lwkt_sendmsg
34594a4cc0bSNuno Antunesand
34694a4cc0bSNuno Antunes.Fn lwkt_replymsg
34794a4cc0bSNuno Antunesfunctions.
34894a4cc0bSNuno AntunesThe putport handler returns
34994a4cc0bSNuno Antunes.Er EASYNC
35094a4cc0bSNuno Antunesfor messages processed asynchronously or any other value for messages processed
35194a4cc0bSNuno Antunessynchronously.
35294a4cc0bSNuno AntunesThat return value of the putport handler is propagated by this function.
35394a4cc0bSNuno AntunesThe
35494a4cc0bSNuno Antunes.Fa port
35594a4cc0bSNuno Antunesargument defines the target port to which the
35694a4cc0bSNuno Antunes.Fa msg
3570d6ab30eSSascha Wildnermessage will be sent.
35894a4cc0bSNuno Antunes.Pp
35994a4cc0bSNuno AntunesThe
36094a4cc0bSNuno Antunes.Fn lwkt_waitmsg
36194a4cc0bSNuno Antunesfunction puts the caller to sleep until the specified
36294a4cc0bSNuno Antunes.Fa msg
36394a4cc0bSNuno Antunesmessage has been replied to.
36494a4cc0bSNuno AntunesThe
36594a4cc0bSNuno Antunes.Fa flags
36694a4cc0bSNuno Antunesargument defines the flags used for the sleep.
367c0dd70d3SSascha Wildner.Sh IMPLEMENTATION NOTES
368c0dd70d3SSascha WildnerAll the default putport handlers (used when a message is sent) currently
369c0dd70d3SSascha Wildnerimplement asynchronous putports only, i.e.\& all
370c0dd70d3SSascha Wildner.Fn *_putport
371c0dd70d3SSascha Wildnerhandlers return
372c0dd70d3SSascha Wildner.Er EASYNC .
373c0dd70d3SSascha WildnerYou can still have synchronous putport handlers (which are run in the sender's
374c0dd70d3SSascha Wildnercontext) but you have to implement the function yourself and then override the
375c0dd70d3SSascha Wildnerdefault.
376c0dd70d3SSascha Wildner.Pp
377c0dd70d3SSascha WildnerPort handler functions can be overridden with custom functions if required.
378c0dd70d3SSascha WildnerYou can override the default putport handler by either using the
379c0dd70d3SSascha Wildner.Fn lwkt_initport_putonly
380c0dd70d3SSascha Wildnerinitializer, or by manipulating the mp_putport handler pointer directly on the
381c0dd70d3SSascha Wildner.Vt lwkt_port
382c0dd70d3SSascha Wildnerstructure.
383c0dd70d3SSascha Wildner.Pp
384c0dd70d3SSascha WildnerThere is one such case where the putport handler is overridden in
385c0dd70d3SSascha Wildner.Pa sys/net/netisr.c .
386c0dd70d3SSascha WildnerIn that case, the putport handler is overridden to detect a loopback message
387c0dd70d3SSascha Wildner(when the target port belongs to the sending thread).
388c0dd70d3SSascha WildnerThis special putport handler turns the sent message into a direct function call
389c0dd70d3SSascha Wildnerinstead of queueing it to the port.
390c0dd70d3SSascha Wildner.Pp
391c0dd70d3SSascha WildnerThe
392c0dd70d3SSascha Wildner.Fn lwkt_replymsg
393c0dd70d3SSascha Wildnerfunction works differently depending on the original message request.
394c0dd70d3SSascha WildnerIf the
395c0dd70d3SSascha Wildnermessage was originally an asynchronous request, the reply will be queued to the
396c0dd70d3SSascha Wildnersender's reply port.
397c0dd70d3SSascha WildnerIf the message was originally a synchronous request, then
398c0dd70d3SSascha Wildnerthis function will just write the error response on the message and wake up the
399c0dd70d3SSascha Wildnerwaiter without queueing the message to the reply port.
400c0dd70d3SSascha WildnerThere is no need to queue in the synchronous request case because the original
401c0dd70d3SSascha Wildnersender had blocked waiting on this specific message with
402c0dd70d3SSascha Wildner.Fn lwkt_domsg .
403c0dd70d3SSascha Wildner.Pp
404c0dd70d3SSascha WildnerAs is the case with putport handler, the replyport handler can also be
405c0dd70d3SSascha Wildneroverridden.
406c0dd70d3SSascha WildnerYou override the default replyport handler by using the
407c0dd70d3SSascha Wildner.Fn lwkt_initport_replyonly
408c0dd70d3SSascha Wildneror the
409c0dd70d3SSascha Wildner.Fn lwkt_initport_replyonly_null
410c0dd70d3SSascha Wildnerport initializers, or by manipulating the mp_replyport handler pointer directly
411c0dd70d3SSascha Wildneron the
412c0dd70d3SSascha Wildner.Vt lwkt_port
413c0dd70d3SSascha Wildnerstructure.
414c0dd70d3SSascha Wildner.Pp
415c0dd70d3SSascha WildnerThe sent message structure is reused for replies.
416c0dd70d3SSascha WildnerWhen a message is replied to, the error response is written on the message
417c0dd70d3SSascha Wildnerwhich is subsequently sent to the reply port.
41894a4cc0bSNuno Antunes.Sh FILES
41994a4cc0bSNuno AntunesThe LWKT msgport implementation resides in
42094a4cc0bSNuno Antunes.Pa sys/kern/lwkt_msgport.c .
42194a4cc0bSNuno Antunes.Sh EXAMPLES
42294a4cc0bSNuno Antunes.Bd -literal
42394a4cc0bSNuno Antunes/*
42494a4cc0bSNuno Antunes * Example 1: per CPU threads.
42594a4cc0bSNuno Antunes *
42694a4cc0bSNuno Antunes */
42794a4cc0bSNuno Antunes
42894a4cc0bSNuno Antunes#include <sys/thread.h>
42994a4cc0bSNuno Antunes#include <sys/msgport.h>
43094a4cc0bSNuno Antunes#include <sys/msgport2.h>
43194a4cc0bSNuno Antunes
43294a4cc0bSNuno Antunesstatic void my_service_loop(void *dummy);
43394a4cc0bSNuno Antuneslwkt_port_t my_service_portfn(int cpu);
43494a4cc0bSNuno Antunesvoid my_service_sendmsg(lwkt_msg_t lmsg, int cpu);
43594a4cc0bSNuno Antunesint my_service_domsg(lwkt_msg_t lmsg, int cpu);
43694a4cc0bSNuno Antunes
43794a4cc0bSNuno Antunes/* Array of per-CPU target ports */
43894a4cc0bSNuno Antunesstruct lwkt_port *my_service_ports[MAXCPU];
43994a4cc0bSNuno Antunes
44094a4cc0bSNuno Antunes/*
441c0dd70d3SSascha Wildner * Create per-cpu threads for handling msg processing.  Remember that
442c0dd70d3SSascha Wildner * built-in lwkt ports are automatically initialized to type 'thread'
443c0dd70d3SSascha Wildner * so we don't need to initialize them explicitly.
44494a4cc0bSNuno Antunes */
44594a4cc0bSNuno Antunesstatic void
44694a4cc0bSNuno Antunesmy_per_cpu_service_init(void)
44794a4cc0bSNuno Antunes{
44894a4cc0bSNuno Antunes	int i;
44994a4cc0bSNuno Antunes	thread_t td;
45094a4cc0bSNuno Antunes
45194a4cc0bSNuno Antunes	for (i = 0; i < ncpus; ++i) {
45294a4cc0bSNuno Antunes		lwkt_create(my_service_loop, NULL, &td,
45394a4cc0bSNuno Antunes			    NULL, 0, i, "myservice_cpu %d", i);
45494a4cc0bSNuno Antunes		my_service_ports[i] = &td->td_msgport;
45594a4cc0bSNuno Antunes	}
45694a4cc0bSNuno Antunes}
45794a4cc0bSNuno Antunes
45894a4cc0bSNuno Antunes/*
45994a4cc0bSNuno Antunes * This is the routine executed by the service threads on each CPU.
46094a4cc0bSNuno Antunes */
46194a4cc0bSNuno Antunesstatic void
46294a4cc0bSNuno Antunesmy_service_loop(void *dummy __unused)
46394a4cc0bSNuno Antunes{
46494a4cc0bSNuno Antunes	lwkt_msg_t msg;
46594a4cc0bSNuno Antunes	thread_t td = curthread;
46694a4cc0bSNuno Antunes	int cpu = curthread->td_gd->gd_cpuid;
46794a4cc0bSNuno Antunes
46894a4cc0bSNuno Antunes	while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) {
46994a4cc0bSNuno Antunes		/* Do some work in the receiver thread context. */
47094a4cc0bSNuno Antunes		kprintf("Received message on CPU %d.\en", cpu);
47194a4cc0bSNuno Antunes
47294a4cc0bSNuno Antunes		/* And finally reply to the message. */
47394a4cc0bSNuno Antunes		lwkt_replymsg(msg, 0);
47494a4cc0bSNuno Antunes	}
47594a4cc0bSNuno Antunes}
47694a4cc0bSNuno Antunes
47794a4cc0bSNuno Antunes/*
47894a4cc0bSNuno Antunes * Given a CPU id, return our respective service port.
47994a4cc0bSNuno Antunes */
48094a4cc0bSNuno Antunes__inline lwkt_port_t
48194a4cc0bSNuno Antunesmy_service_portfn(int cpu)
48294a4cc0bSNuno Antunes{
48394a4cc0bSNuno Antunes	return my_service_ports[cpu];
48494a4cc0bSNuno Antunes}
48594a4cc0bSNuno Antunes
48694a4cc0bSNuno Antunes/*
48794a4cc0bSNuno Antunes * Send an asynchronous message to the service thread on a specific CPU.
48894a4cc0bSNuno Antunes */
48994a4cc0bSNuno Antunesvoid
49094a4cc0bSNuno Antunesmy_service_sendmsg(lwkt_msg_t lmsg, int cpu)
49194a4cc0bSNuno Antunes{
49294a4cc0bSNuno Antunes	KKASSERT(cpu < ncpus);
49394a4cc0bSNuno Antunes	lwkt_sendmsg(my_service_portfn(cpu), lmsg);
49494a4cc0bSNuno Antunes}
49594a4cc0bSNuno Antunes
49694a4cc0bSNuno Antunes/*
49794a4cc0bSNuno Antunes * Send a synchronous message to the service thread on a specific CPU.
49894a4cc0bSNuno Antunes */
49994a4cc0bSNuno Antunesint
50094a4cc0bSNuno Antunesmy_service_domsg(lwkt_msg_t lmsg, int cpu)
50194a4cc0bSNuno Antunes{
50294a4cc0bSNuno Antunes	KKASSERT(cpu < ncpus);
50394a4cc0bSNuno Antunes	return lwkt_domsg(my_service_portfn(cpu), lmsg, 0);
50494a4cc0bSNuno Antunes}
50594a4cc0bSNuno Antunes
50694a4cc0bSNuno Antunes/*
50794a4cc0bSNuno Antunes * Example use case. Initialize the service threads and send each one a
50894a4cc0bSNuno Antunes * message.
50994a4cc0bSNuno Antunes */
51094a4cc0bSNuno Antunesstatic void
51194a4cc0bSNuno Antunesmod_load(void)
51294a4cc0bSNuno Antunes{
51394a4cc0bSNuno Antunes	lwkt_msg	lmsg;
51494a4cc0bSNuno Antunes	lwkt_port_t	builtin_port = &curthread->td_msgport;
51594a4cc0bSNuno Antunes	int		i;
51694a4cc0bSNuno Antunes
51794a4cc0bSNuno Antunes	my_per_cpu_service_init();
51894a4cc0bSNuno Antunes	for (i=0; i<ncpus; ++i) {
51994a4cc0bSNuno Antunes		kprintf("Sending msg to CPU %d.\en", i);
52094a4cc0bSNuno Antunes		lwkt_initmsg(&lmsg, builtin_port, 0);
52194a4cc0bSNuno Antunes		my_service_domsg(&lmsg, i);
52294a4cc0bSNuno Antunes	}
52394a4cc0bSNuno Antunes}
52494a4cc0bSNuno Antunes
52594a4cc0bSNuno Antunes/*
52694a4cc0bSNuno Antunes * Example 2: Dynamic allocated message passing with automatic free.
52794a4cc0bSNuno Antunes *
528c0dd70d3SSascha Wildner * This scenario is used when resources need to be freed after the
529c0dd70d3SSascha Wildner * message has been replied to. Features:
53094a4cc0bSNuno Antunes * - An argument is passed within the message.
531c0dd70d3SSascha Wildner * - Messages are allocated with kmalloc(). Replying to the message
532c0dd70d3SSascha Wildner *   kfree()s it.
53394a4cc0bSNuno Antunes */
53494a4cc0bSNuno Antunes
53594a4cc0bSNuno Antunes#include <sys/thread.h>
53694a4cc0bSNuno Antunes#include <sys/msgport.h>
53794a4cc0bSNuno Antunes#include <sys/msgport2.h>
53894a4cc0bSNuno Antunes
53994a4cc0bSNuno Antunesvoid my_service_queue(void *arg);
54094a4cc0bSNuno Antunes
54194a4cc0bSNuno Antuneslwkt_port my_autofree_rport;
54294a4cc0bSNuno Antuneslwkt_port_t my_service_port;
54394a4cc0bSNuno Antunes
54494a4cc0bSNuno Antunes/*
54594a4cc0bSNuno Antunes * Use this function to send messages with a void * argument to our
54694a4cc0bSNuno Antunes * service thread.
54794a4cc0bSNuno Antunes */
54894a4cc0bSNuno Antunesvoid
54994a4cc0bSNuno Antunesmy_service_queue(void *arg)
55094a4cc0bSNuno Antunes{
55194a4cc0bSNuno Antunes	lwkt_msg_t msg;
55294a4cc0bSNuno Antunes
55394a4cc0bSNuno Antunes	msg = kmalloc(sizeof(*msg), M_TEMP, M_WAITOK);
55494a4cc0bSNuno Antunes
55594a4cc0bSNuno Antunes	/* Set reply port to autofree. */
55694a4cc0bSNuno Antunes	lwkt_initmsg(msg, &my_autofree_rport, 0);
55794a4cc0bSNuno Antunes
55894a4cc0bSNuno Antunes	/* Attach the argument to the message. */
55994a4cc0bSNuno Antunes	msg->u.ms_resultp = arg;
56094a4cc0bSNuno Antunes
56194a4cc0bSNuno Antunes	/* Send it. */
56294a4cc0bSNuno Antunes	lwkt_sendmsg(my_service_port, msg);
56394a4cc0bSNuno Antunes}
56494a4cc0bSNuno Antunes
56594a4cc0bSNuno Antunes/*
56694a4cc0bSNuno Antunes * This is the routine executed by our service thread.
56794a4cc0bSNuno Antunes */
56894a4cc0bSNuno Antunesstatic void
56994a4cc0bSNuno Antunesmy_service_loop(void *dummy __unused)
57094a4cc0bSNuno Antunes{
57194a4cc0bSNuno Antunes	lwkt_msg_t msg;
57294a4cc0bSNuno Antunes	thread_t td = curthread;
57394a4cc0bSNuno Antunes
57494a4cc0bSNuno Antunes	while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) {
57594a4cc0bSNuno Antunes		/*
57694a4cc0bSNuno Antunes		 * Do some work in the receiver thread context.  In this
57794a4cc0bSNuno Antunes		 * example, the sender wrote his name in the argument he
57894a4cc0bSNuno Antunes		 * sent us.  We print it here.
57994a4cc0bSNuno Antunes		 */
58094a4cc0bSNuno Antunes		char *arg = msg->u.ms_resultp;
581c0dd70d3SSascha Wildner		kprintf("%s: Hi %s! Got your msg.\en", curthread->td_comm,
582c0dd70d3SSascha Wildner		    arg);
58394a4cc0bSNuno Antunes
58494a4cc0bSNuno Antunes		/* And finally reply to the message. */
58594a4cc0bSNuno Antunes		lwkt_replymsg(msg, 0);
58694a4cc0bSNuno Antunes	}
58794a4cc0bSNuno Antunes}
58894a4cc0bSNuno Antunes
58994a4cc0bSNuno Antunesstatic void
59094a4cc0bSNuno Antunesmy_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
59194a4cc0bSNuno Antunes{
59294a4cc0bSNuno Antunes	kfree(msg->u.ms_resultp, M_TEMP);
59394a4cc0bSNuno Antunes	kfree(msg, M_TEMP);
59494a4cc0bSNuno Antunes}
59594a4cc0bSNuno Antunes
59694a4cc0bSNuno Antunesstatic void
59794a4cc0bSNuno Antunesmy_service_init(void)
59894a4cc0bSNuno Antunes{
59994a4cc0bSNuno Antunes	thread_t tdp;
60094a4cc0bSNuno Antunes
60194a4cc0bSNuno Antunes	/* Initialize our auto free reply port. */
60294a4cc0bSNuno Antunes	lwkt_initport_replyonly(&my_autofree_rport, my_autofree_reply);
60394a4cc0bSNuno Antunes
60494a4cc0bSNuno Antunes	/* Create our service thread on CPU 0. */
60594a4cc0bSNuno Antunes	lwkt_create(my_service_loop, NULL, &tdp, NULL, 0, 0, "myservice");
60694a4cc0bSNuno Antunes	my_service_port = &tdp->td_msgport;
60794a4cc0bSNuno Antunes}
60894a4cc0bSNuno Antunes
60994a4cc0bSNuno Antunes/*
610c0dd70d3SSascha Wildner * Example use case. Initialize the service and send the current thread
611c0dd70d3SSascha Wildner * name to the service thread.
61294a4cc0bSNuno Antunes */
61394a4cc0bSNuno Antunesstatic void
61494a4cc0bSNuno Antunesmod_load(void)
61594a4cc0bSNuno Antunes{
61694a4cc0bSNuno Antunes	void *arg;
61794a4cc0bSNuno Antunes	int len;
61894a4cc0bSNuno Antunes
61994a4cc0bSNuno Antunes	my_service_init();
62094a4cc0bSNuno Antunes	len = strlen(curthread->td_comm);
62194a4cc0bSNuno Antunes	arg = kmalloc(len + 1, M_TEMP, M_WAITOK);
62294a4cc0bSNuno Antunes	bcopy(curthread->td_comm, arg, len + 1);
62394a4cc0bSNuno Antunes	kprintf("%s: Sending message.\en", curthread->td_comm);
62494a4cc0bSNuno Antunes	my_service_queue(arg);
62594a4cc0bSNuno Antunes}
62694a4cc0bSNuno Antunes.Ed
62794a4cc0bSNuno Antunes.Sh SEE ALSO
62894a4cc0bSNuno Antunes.Xr serializer 9 ,
6297cb54419SNuno Antunes.Xr sleep 9 ,
6307cb54419SNuno Antunes.Xr spinlock 9
63194a4cc0bSNuno Antunes.Sh HISTORY
63294a4cc0bSNuno AntunesThe LWKT msgport interface first appeared in
63394a4cc0bSNuno Antunes.Dx 1.0 .
63494a4cc0bSNuno Antunes.Sh AUTHORS
63594a4cc0bSNuno Antunes.An -nosplit
63694a4cc0bSNuno AntunesThe
63794a4cc0bSNuno Antunes.Nm msgport
63894a4cc0bSNuno Antunesmessage passing interface implementation was written by
63994a4cc0bSNuno Antunes.An Matthew Dillon .
64094a4cc0bSNuno AntunesThis manual page was written by
64194a4cc0bSNuno Antunes.An Nuno Antunes .
642