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