194a4cc0bSNuno Antunes.\" 294a4cc0bSNuno Antunes.\" Copyright (c) 2012 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.\" 3494a4cc0bSNuno Antunes.Dd August 12, 2012 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 6494a4cc0bSNuno Antunes.Fn lwkt_initport_spin "lwkt_port_t port" 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" 10094a4cc0bSNuno Antunes.Ft void 10194a4cc0bSNuno Antunes.Fn lwkt_dropmsg "lwkt_msg_t msg" 10294a4cc0bSNuno Antunes.Sh DESCRIPTION 103*c6e8b6c1SSascha WildnerLight weight kernel threads in 104*c6e8b6c1SSascha Wildner.Dx 105*c6e8b6c1SSascha 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 11994a4cc0bSNuno AntunesPorts of type 'thread' are owned by a single light weight kernel thread. 12094a4cc0bSNuno AntunesWhen a message is sent to a port of type 'thread', only the owner of that port 12194a4cc0bSNuno Antunesis allowed to retrieve the message from it. 12294a4cc0bSNuno AntunesWhen a message is sent to a port of type 'spin' or to a port of 12394a4cc0bSNuno Antunestype 'serializer', multiple threads are allowed to check that port for new 12494a4cc0bSNuno Antunesmessages and compete to retrieve them. 12594a4cc0bSNuno AntunesYou define the port type when you initialize the port. 12694a4cc0bSNuno AntunesBy default, the built-in port of every light weight kernel thread is 12794a4cc0bSNuno Antunesautomatically initialized to type 'thread'. 12894a4cc0bSNuno Antunes.Pp 12994a4cc0bSNuno AntunesWhen a message is sent, the receiver should normally send back a reply. 13094a4cc0bSNuno AntunesThe reply is sent to the reply port that is registered on the original message. 13194a4cc0bSNuno AntunesMessages can be replied to synchronously or asynchronously. 13294a4cc0bSNuno AntunesThe sender may request a synchronous or asynchronous reply to the message, 13394a4cc0bSNuno Antuneshowever the target port will ultimately decide how the message will be treated. 13494a4cc0bSNuno Antunes.Sh MESSAGE FUNCTIONS 13594a4cc0bSNuno AntunesMessages must be initialized before being used. 13694a4cc0bSNuno AntunesThe 13794a4cc0bSNuno Antunes.Fn lwkt_initmsg 13894a4cc0bSNuno Antunesfunction initializes a message. 13994a4cc0bSNuno AntunesThe 14094a4cc0bSNuno Antunes.Fa rport 14194a4cc0bSNuno Antunesargument identifies the reply port which will be used for asynchronous replies. 14294a4cc0bSNuno AntunesThe 14394a4cc0bSNuno Antunes.Fa flags 14494a4cc0bSNuno Antunesargument sets any required flags for this message. 14594a4cc0bSNuno AntunesFlags passed this way will simply be or'ed to any already existing flags on the 14694a4cc0bSNuno Antunesmessage. 14794a4cc0bSNuno Antunes.Pp 14894a4cc0bSNuno AntunesThe 14994a4cc0bSNuno Antunes.Fn lwkt_initmsg_abortable 15094a4cc0bSNuno Antunesfunction is similar to 15194a4cc0bSNuno Antunes.Fn lwkt_initmsg 15294a4cc0bSNuno Antunesbut it takes an additional parameter 15394a4cc0bSNuno Antunes.Fa abortfn 15494a4cc0bSNuno Antuneswhich defines the abort function for this message. 15594a4cc0bSNuno Antunes.Pp 15694a4cc0bSNuno AntunesThe 15794a4cc0bSNuno Antunes.Fn lwkt_sendmsg 15894a4cc0bSNuno Antunesfunction requests an asynchronous reply, sends the message and returns 15994a4cc0bSNuno Antunesimmediately. 16094a4cc0bSNuno AntunesUnder normal circumstances, users of this function may always expect the reply 16194a4cc0bSNuno Antunesto be queued to the reply port registered on the message. 16294a4cc0bSNuno AntunesThe 16394a4cc0bSNuno Antunes.Fa port 16494a4cc0bSNuno Antunesargument defines the target port to which the 16594a4cc0bSNuno Antunes.Fa msg 16694a4cc0bSNuno Antunesmessage will be sent to. 16794a4cc0bSNuno Antunes.Pp 16894a4cc0bSNuno AntunesThe 16994a4cc0bSNuno Antunes.Fn lwkt_domsg 17094a4cc0bSNuno Antunesfunction requests a synchronous reply, sends the message and does not return 17194a4cc0bSNuno Antunesuntil the message has been replied to. 17294a4cc0bSNuno AntunesIf the target port supports synchronous reply, this function will return that 17394a4cc0bSNuno Antunesreply immediately. 17494a4cc0bSNuno AntunesIf not, and this is the most common case, this function will block and wait for the 17594a4cc0bSNuno Antunesreply to arrive and then return it. 17694a4cc0bSNuno AntunesThe 17794a4cc0bSNuno Antunes.Fa port 17894a4cc0bSNuno Antunesargument defines the target port to which the 17994a4cc0bSNuno Antunes.Fa msg 18094a4cc0bSNuno Antunesmessage will be sent to. 18194a4cc0bSNuno Antunes.Pp 18294a4cc0bSNuno AntunesThe 18394a4cc0bSNuno Antunes.Fn lwkt_replymsg 18494a4cc0bSNuno Antunesfunction replies to a message that was processed asynchronously by the target 18594a4cc0bSNuno Antunesport. 18694a4cc0bSNuno AntunesThis function is used by the thread on the receiving side. 18794a4cc0bSNuno AntunesThe 18894a4cc0bSNuno Antunes.Fa msg 18994a4cc0bSNuno Antunesargument is the message being replied to and the 19094a4cc0bSNuno Antunes.Fa error 19194a4cc0bSNuno Antunesargument is the actual response to send back. 19294a4cc0bSNuno Antunes.Pp 19394a4cc0bSNuno AntunesThe 19494a4cc0bSNuno Antunes.Fn lwkt_forwardmsg 19594a4cc0bSNuno Antunessimply forwards a message to another port. 19694a4cc0bSNuno AntunesThe 19794a4cc0bSNuno Antunes.Fa port 19894a4cc0bSNuno Antunesargument defines the target port to which the 19994a4cc0bSNuno Antunes.Fa msg 20094a4cc0bSNuno Antunesmessage will be sent to. 20194a4cc0bSNuno Antunes.Pp 20294a4cc0bSNuno AntunesIf a message has been initialized as abortable, you can use the 20394a4cc0bSNuno Antunes.Fn lwkt_abortmsg 20494a4cc0bSNuno Antunesfunction to try to abort it. 20594a4cc0bSNuno AntunesThe 20694a4cc0bSNuno Antunes.Fa abortfn 20794a4cc0bSNuno Antunespassed upon the initialisation with 20894a4cc0bSNuno Antunes.Fn lwkt_initmsg_abortable 20994a4cc0bSNuno Antuneswill be called by this function. 21094a4cc0bSNuno Antunes.Pp 21194a4cc0bSNuno AntunesThe 21294a4cc0bSNuno Antunes.Fn lwkt_dropmsg 21394a4cc0bSNuno Antuneswill dequeue the specified message from the target port it was sent to and makes 21494a4cc0bSNuno Antunesit look like it was never sent. 21594a4cc0bSNuno Antunes.Sh PORT FUNCTIONS 21694a4cc0bSNuno AntunesThe 21794a4cc0bSNuno Antunes.Fn lwkt_initport_thread 21894a4cc0bSNuno Antunesinitializes the specified 21994a4cc0bSNuno Antunes.Fa port 22094a4cc0bSNuno Antuneswith the default 'thread' port type handlers. 22194a4cc0bSNuno AntunesThe 22294a4cc0bSNuno Antunes.Fa td 22394a4cc0bSNuno Antunesargument defines the owner thread of the port and only that thread is allowed to 22494a4cc0bSNuno Antunesreceive messages on it. 22594a4cc0bSNuno Antunes.Pp 22694a4cc0bSNuno AntunesThe 22794a4cc0bSNuno Antunes.Fn lwkt_initport_spin 22894a4cc0bSNuno Antunesinitializes the specified 22994a4cc0bSNuno Antunes.Fa port 23094a4cc0bSNuno Antuneswith the default 'spin' port type handlers. 23194a4cc0bSNuno AntunesIt will also initialize the embedded spinlock within the 23294a4cc0bSNuno Antuneslwkt_port structure which will protect subsequent port access. 23394a4cc0bSNuno Antunes.Pp 23494a4cc0bSNuno AntunesThe 23594a4cc0bSNuno Antunes.Fn lwkt_initport_serialize 23694a4cc0bSNuno Antunesfunction initializes the specified 23794a4cc0bSNuno Antunes.Fa port 23894a4cc0bSNuno Antuneswith the default 'serializer' port type handlers. 23994a4cc0bSNuno AntunesThe subsequent port access will be protected by the passed 24094a4cc0bSNuno Antunes.Fa slz 24194a4cc0bSNuno Antunesserializer lock. 24294a4cc0bSNuno Antunes.Pp 24394a4cc0bSNuno AntunesThe 24494a4cc0bSNuno Antunes.Fn lwkt_getport 24594a4cc0bSNuno Antunesfunction checks the specified 24694a4cc0bSNuno Antunes.Fa port 24794a4cc0bSNuno Antunesfor available messages, dequeues the first one and returns it. 24894a4cc0bSNuno AntunesIf no messages are available then 24994a4cc0bSNuno Antunes.Dv NULL 25094a4cc0bSNuno Antunesis returned instead. 25194a4cc0bSNuno AntunesThis function is used by threads on the receiving side. 25294a4cc0bSNuno Antunes.Pp 25394a4cc0bSNuno AntunesThe 25494a4cc0bSNuno Antunes.Fn lwkt_waitport 25594a4cc0bSNuno Antunesfunction checks the specified 25694a4cc0bSNuno Antunes.Fa port 25794a4cc0bSNuno Antunesfor available messages, dequeues the first one and returns it. 25894a4cc0bSNuno AntunesIf no messages are available then the caller thread will sleep until a message 25994a4cc0bSNuno Antunesarrives on the specified port. 26094a4cc0bSNuno AntunesThe 26194a4cc0bSNuno Antunes.Fa flags 26294a4cc0bSNuno Antunesargument defines the flags used for the sleep. 26394a4cc0bSNuno AntunesThis function is used by threads on the receiving side. 26494a4cc0bSNuno Antunes.Sh SPECIAL PORT INITIALIZERS 26594a4cc0bSNuno AntunesThe 26694a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly 26794a4cc0bSNuno Antunesfunction initializes a 26894a4cc0bSNuno Antunes.Fa port 26994a4cc0bSNuno Antuneswhich is used only as reply port and may have a custom reply port handler. 27094a4cc0bSNuno AntunesThe reply port handler is specified with the 27194a4cc0bSNuno Antunes.Fa rportfn 27294a4cc0bSNuno Antunesargument. 27394a4cc0bSNuno AntunesAll the other handlers will panic the system if they are called. 27494a4cc0bSNuno AntunesThis initializer is normally used on ports for freeing resources after the 27594a4cc0bSNuno Antunesmessages have fulfilled their purpose. 27694a4cc0bSNuno Antunes.Pp 27794a4cc0bSNuno AntunesThe 27894a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly_null 27994a4cc0bSNuno Antunesfunction initializes a 28094a4cc0bSNuno Antunes.Fa port 28194a4cc0bSNuno Antuneswhich is used only as reply port. 28294a4cc0bSNuno AntunesThe reply port handler will simply mark the message as being done and will not 28394a4cc0bSNuno Antunesattempt to queue it. 28494a4cc0bSNuno AntunesAll the other handlers will panic the system if they are called. 28594a4cc0bSNuno Antunes.Pp 28694a4cc0bSNuno AntunesThe 28794a4cc0bSNuno Antunes.Fn lwkt_initport_putonly 28894a4cc0bSNuno Antunesfunction initializes a 28994a4cc0bSNuno Antunes.Fa port 29094a4cc0bSNuno Antuneswhich is used only as target port. 29194a4cc0bSNuno AntunesThe putport handler is specified with the 29294a4cc0bSNuno Antunes.Fa pportfn 29394a4cc0bSNuno Antunesargument. 29494a4cc0bSNuno AntunesAll the other handlers will panic the system if they are called. 29594a4cc0bSNuno Antunes.Pp 29694a4cc0bSNuno AntunesThe 29794a4cc0bSNuno Antunes.Fn lwkt_initport_panic 29894a4cc0bSNuno Antunesfunction initializes a 29994a4cc0bSNuno Antunes.Fa port 30094a4cc0bSNuno Antuneswhich will panic the system if any of its handlers are called. 30194a4cc0bSNuno AntunesThis function is sometimes used to initialize a reply-only port which does not 302*c6e8b6c1SSascha Wildnerexpect the messages to be replied to, e.g.\& when the messages should be 303*c6e8b6c1SSascha Wildnerconsumed by the receiving thread and never replied back. 30494a4cc0bSNuno Antunes.Sh INTERNAL MESSAGE FUNCTIONS 30594a4cc0bSNuno AntunesThe following functions are used only by the infrastructure, you should not 30694a4cc0bSNuno Antunesneed to use them directly unless in very rare cases. 30794a4cc0bSNuno Antunes.Pp 30894a4cc0bSNuno AntunesThe 30994a4cc0bSNuno Antunes.Fn lwkt_beginmsg 31094a4cc0bSNuno Antunesfunction simply calls the target port's putport handler. 31194a4cc0bSNuno AntunesThis function is only called by the 31294a4cc0bSNuno Antunes.Fn lwkt_sendmsg 31394a4cc0bSNuno Antunesand 31494a4cc0bSNuno Antunes.Fn lwkt_replymsg 31594a4cc0bSNuno Antunesfunctions. 31694a4cc0bSNuno AntunesThe putport handler returns 31794a4cc0bSNuno Antunes.Er EASYNC 31894a4cc0bSNuno Antunesfor messages processed asynchronously or any other value for messages processed 31994a4cc0bSNuno Antunessynchronously. 32094a4cc0bSNuno AntunesThat return value of the putport handler is propagated by this function. 32194a4cc0bSNuno AntunesThe 32294a4cc0bSNuno Antunes.Fa port 32394a4cc0bSNuno Antunesargument defines the target port to which the 32494a4cc0bSNuno Antunes.Fa msg 32594a4cc0bSNuno Antunesmessage will be sent to. 32694a4cc0bSNuno Antunes.Pp 32794a4cc0bSNuno AntunesThe 32894a4cc0bSNuno Antunes.Fn lwkt_waitmsg 32994a4cc0bSNuno Antunesfunction puts the caller to sleep until the specified 33094a4cc0bSNuno Antunes.Fa msg 33194a4cc0bSNuno Antunesmessage has been replied to. 33294a4cc0bSNuno AntunesThe 33394a4cc0bSNuno Antunes.Fa flags 33494a4cc0bSNuno Antunesargument defines the flags used for the sleep. 33594a4cc0bSNuno Antunes.Sh FILES 33694a4cc0bSNuno AntunesThe LWKT msgport implementation resides in 33794a4cc0bSNuno Antunes.Pa sys/kern/lwkt_msgport.c . 33894a4cc0bSNuno Antunes.Sh EXAMPLES 33994a4cc0bSNuno Antunes.Bd -literal 34094a4cc0bSNuno Antunes/* 34194a4cc0bSNuno Antunes * Example 1: per CPU threads. 34294a4cc0bSNuno Antunes * 34394a4cc0bSNuno Antunes */ 34494a4cc0bSNuno Antunes 34594a4cc0bSNuno Antunes#include <sys/thread.h> 34694a4cc0bSNuno Antunes#include <sys/msgport.h> 34794a4cc0bSNuno Antunes#include <sys/msgport2.h> 34894a4cc0bSNuno Antunes 34994a4cc0bSNuno Antunesstatic void my_service_loop(void *dummy); 35094a4cc0bSNuno Antuneslwkt_port_t my_service_portfn(int cpu); 35194a4cc0bSNuno Antunesvoid my_service_sendmsg(lwkt_msg_t lmsg, int cpu); 35294a4cc0bSNuno Antunesint my_service_domsg(lwkt_msg_t lmsg, int cpu); 35394a4cc0bSNuno Antunes 35494a4cc0bSNuno Antunes/* Array of per-CPU target ports */ 35594a4cc0bSNuno Antunesstruct lwkt_port *my_service_ports[MAXCPU]; 35694a4cc0bSNuno Antunes 35794a4cc0bSNuno Antunes/* 35894a4cc0bSNuno Antunes * Create per-cpu threads for handling msg processing. Remember that built-in 35994a4cc0bSNuno Antunes * lwkt ports are automatically initialized to type 'thread' so we don't need 36094a4cc0bSNuno Antunes * to initialize them explicitly. 36194a4cc0bSNuno Antunes */ 36294a4cc0bSNuno Antunesstatic void 36394a4cc0bSNuno Antunesmy_per_cpu_service_init(void) 36494a4cc0bSNuno Antunes{ 36594a4cc0bSNuno Antunes int i; 36694a4cc0bSNuno Antunes thread_t td; 36794a4cc0bSNuno Antunes 36894a4cc0bSNuno Antunes for (i = 0; i < ncpus; ++i) { 36994a4cc0bSNuno Antunes lwkt_create(my_service_loop, NULL, &td, 37094a4cc0bSNuno Antunes NULL, 0, i, "myservice_cpu %d", i); 37194a4cc0bSNuno Antunes my_service_ports[i] = &td->td_msgport; 37294a4cc0bSNuno Antunes } 37394a4cc0bSNuno Antunes} 37494a4cc0bSNuno Antunes 37594a4cc0bSNuno Antunes/* 37694a4cc0bSNuno Antunes * This is the routine executed by the service threads on each CPU. 37794a4cc0bSNuno Antunes */ 37894a4cc0bSNuno Antunesstatic void 37994a4cc0bSNuno Antunesmy_service_loop(void *dummy __unused) 38094a4cc0bSNuno Antunes{ 38194a4cc0bSNuno Antunes lwkt_msg_t msg; 38294a4cc0bSNuno Antunes thread_t td = curthread; 38394a4cc0bSNuno Antunes int cpu = curthread->td_gd->gd_cpuid; 38494a4cc0bSNuno Antunes 38594a4cc0bSNuno Antunes while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 38694a4cc0bSNuno Antunes /* Do some work in the receiver thread context. */ 38794a4cc0bSNuno Antunes kprintf("Received message on CPU %d.\en", cpu); 38894a4cc0bSNuno Antunes 38994a4cc0bSNuno Antunes /* And finally reply to the message. */ 39094a4cc0bSNuno Antunes lwkt_replymsg(msg, 0); 39194a4cc0bSNuno Antunes } 39294a4cc0bSNuno Antunes} 39394a4cc0bSNuno Antunes 39494a4cc0bSNuno Antunes/* 39594a4cc0bSNuno Antunes * Given a CPU id, return our respective service port. 39694a4cc0bSNuno Antunes */ 39794a4cc0bSNuno Antunes__inline lwkt_port_t 39894a4cc0bSNuno Antunesmy_service_portfn(int cpu) 39994a4cc0bSNuno Antunes{ 40094a4cc0bSNuno Antunes return my_service_ports[cpu]; 40194a4cc0bSNuno Antunes} 40294a4cc0bSNuno Antunes 40394a4cc0bSNuno Antunes/* 40494a4cc0bSNuno Antunes * Send an asynchronous message to the service thread on a specific CPU. 40594a4cc0bSNuno Antunes */ 40694a4cc0bSNuno Antunesvoid 40794a4cc0bSNuno Antunesmy_service_sendmsg(lwkt_msg_t lmsg, int cpu) 40894a4cc0bSNuno Antunes{ 40994a4cc0bSNuno Antunes KKASSERT(cpu < ncpus); 41094a4cc0bSNuno Antunes lwkt_sendmsg(my_service_portfn(cpu), lmsg); 41194a4cc0bSNuno Antunes} 41294a4cc0bSNuno Antunes 41394a4cc0bSNuno Antunes/* 41494a4cc0bSNuno Antunes * Send a synchronous message to the service thread on a specific CPU. 41594a4cc0bSNuno Antunes */ 41694a4cc0bSNuno Antunesint 41794a4cc0bSNuno Antunesmy_service_domsg(lwkt_msg_t lmsg, int cpu) 41894a4cc0bSNuno Antunes{ 41994a4cc0bSNuno Antunes KKASSERT(cpu < ncpus); 42094a4cc0bSNuno Antunes return lwkt_domsg(my_service_portfn(cpu), lmsg, 0); 42194a4cc0bSNuno Antunes} 42294a4cc0bSNuno Antunes 42394a4cc0bSNuno Antunes/* 42494a4cc0bSNuno Antunes * Example use case. Initialize the service threads and send each one a 42594a4cc0bSNuno Antunes * message. 42694a4cc0bSNuno Antunes */ 42794a4cc0bSNuno Antunesstatic void 42894a4cc0bSNuno Antunesmod_load(void) 42994a4cc0bSNuno Antunes{ 43094a4cc0bSNuno Antunes lwkt_msg lmsg; 43194a4cc0bSNuno Antunes lwkt_port_t builtin_port = &curthread->td_msgport; 43294a4cc0bSNuno Antunes int i; 43394a4cc0bSNuno Antunes 43494a4cc0bSNuno Antunes my_per_cpu_service_init(); 43594a4cc0bSNuno Antunes for (i=0; i<ncpus; ++i) { 43694a4cc0bSNuno Antunes kprintf("Sending msg to CPU %d.\en", i); 43794a4cc0bSNuno Antunes lwkt_initmsg(&lmsg, builtin_port, 0); 43894a4cc0bSNuno Antunes my_service_domsg(&lmsg, i); 43994a4cc0bSNuno Antunes } 44094a4cc0bSNuno Antunes} 44194a4cc0bSNuno Antunes 44294a4cc0bSNuno Antunes/* 44394a4cc0bSNuno Antunes * Example 2: Dynamic allocated message passing with automatic free. 44494a4cc0bSNuno Antunes * 44594a4cc0bSNuno Antunes * This scenario is used when resources need to be freed after the message 44694a4cc0bSNuno Antunes * has been replied to. Features: 44794a4cc0bSNuno Antunes * - An argument is passed within the message. 44894a4cc0bSNuno Antunes * - Messages are allocated with kmalloc(). Replying to the msg, kfree()s it. 44994a4cc0bSNuno Antunes */ 45094a4cc0bSNuno Antunes 45194a4cc0bSNuno Antunes#include <sys/thread.h> 45294a4cc0bSNuno Antunes#include <sys/msgport.h> 45394a4cc0bSNuno Antunes#include <sys/msgport2.h> 45494a4cc0bSNuno Antunes 45594a4cc0bSNuno Antunesvoid my_service_queue(void *arg); 45694a4cc0bSNuno Antunes 45794a4cc0bSNuno Antuneslwkt_port my_autofree_rport; 45894a4cc0bSNuno Antuneslwkt_port_t my_service_port; 45994a4cc0bSNuno Antunes 46094a4cc0bSNuno Antunes/* 46194a4cc0bSNuno Antunes * Use this function to send messages with a void * argument to our 46294a4cc0bSNuno Antunes * service thread. 46394a4cc0bSNuno Antunes */ 46494a4cc0bSNuno Antunesvoid 46594a4cc0bSNuno Antunesmy_service_queue(void *arg) 46694a4cc0bSNuno Antunes{ 46794a4cc0bSNuno Antunes lwkt_msg_t msg; 46894a4cc0bSNuno Antunes 46994a4cc0bSNuno Antunes msg = kmalloc(sizeof(*msg), M_TEMP, M_WAITOK); 47094a4cc0bSNuno Antunes 47194a4cc0bSNuno Antunes /* Set reply port to autofree. */ 47294a4cc0bSNuno Antunes lwkt_initmsg(msg, &my_autofree_rport, 0); 47394a4cc0bSNuno Antunes 47494a4cc0bSNuno Antunes /* Attach the argument to the message. */ 47594a4cc0bSNuno Antunes msg->u.ms_resultp = arg; 47694a4cc0bSNuno Antunes 47794a4cc0bSNuno Antunes /* Send it. */ 47894a4cc0bSNuno Antunes lwkt_sendmsg(my_service_port, msg); 47994a4cc0bSNuno Antunes} 48094a4cc0bSNuno Antunes 48194a4cc0bSNuno Antunes/* 48294a4cc0bSNuno Antunes * This is the routine executed by our service thread. 48394a4cc0bSNuno Antunes */ 48494a4cc0bSNuno Antunesstatic void 48594a4cc0bSNuno Antunesmy_service_loop(void *dummy __unused) 48694a4cc0bSNuno Antunes{ 48794a4cc0bSNuno Antunes lwkt_msg_t msg; 48894a4cc0bSNuno Antunes thread_t td = curthread; 48994a4cc0bSNuno Antunes 49094a4cc0bSNuno Antunes while ((msg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 49194a4cc0bSNuno Antunes /* 49294a4cc0bSNuno Antunes * Do some work in the receiver thread context. In this 49394a4cc0bSNuno Antunes * example, the sender wrote his name in the argument he 49494a4cc0bSNuno Antunes * sent us. We print it here. 49594a4cc0bSNuno Antunes */ 49694a4cc0bSNuno Antunes char *arg = msg->u.ms_resultp; 49794a4cc0bSNuno Antunes kprintf("%s: Hi %s! Got your msg.\en", curthread->td_comm, arg); 49894a4cc0bSNuno Antunes 49994a4cc0bSNuno Antunes /* And finally reply to the message. */ 50094a4cc0bSNuno Antunes lwkt_replymsg(msg, 0); 50194a4cc0bSNuno Antunes } 50294a4cc0bSNuno Antunes} 50394a4cc0bSNuno Antunes 50494a4cc0bSNuno Antunesstatic void 50594a4cc0bSNuno Antunesmy_autofree_reply(lwkt_port_t port, lwkt_msg_t msg) 50694a4cc0bSNuno Antunes{ 50794a4cc0bSNuno Antunes kfree(msg->u.ms_resultp, M_TEMP); 50894a4cc0bSNuno Antunes kfree(msg, M_TEMP); 50994a4cc0bSNuno Antunes} 51094a4cc0bSNuno Antunes 51194a4cc0bSNuno Antunesstatic void 51294a4cc0bSNuno Antunesmy_service_init(void) 51394a4cc0bSNuno Antunes{ 51494a4cc0bSNuno Antunes thread_t tdp; 51594a4cc0bSNuno Antunes 51694a4cc0bSNuno Antunes /* Initialize our auto free reply port. */ 51794a4cc0bSNuno Antunes lwkt_initport_replyonly(&my_autofree_rport, my_autofree_reply); 51894a4cc0bSNuno Antunes 51994a4cc0bSNuno Antunes /* Create our service thread on CPU 0. */ 52094a4cc0bSNuno Antunes lwkt_create(my_service_loop, NULL, &tdp, NULL, 0, 0, "myservice"); 52194a4cc0bSNuno Antunes my_service_port = &tdp->td_msgport; 52294a4cc0bSNuno Antunes} 52394a4cc0bSNuno Antunes 52494a4cc0bSNuno Antunes/* 52594a4cc0bSNuno Antunes * Example use case. Initialize the service and send the current thread name 52694a4cc0bSNuno Antunes * to the service thread. 52794a4cc0bSNuno Antunes */ 52894a4cc0bSNuno Antunesstatic void 52994a4cc0bSNuno Antunesmod_load(void) 53094a4cc0bSNuno Antunes{ 53194a4cc0bSNuno Antunes void *arg; 53294a4cc0bSNuno Antunes int len; 53394a4cc0bSNuno Antunes 53494a4cc0bSNuno Antunes my_service_init(); 53594a4cc0bSNuno Antunes len = strlen(curthread->td_comm); 53694a4cc0bSNuno Antunes arg = kmalloc(len + 1, M_TEMP, M_WAITOK); 53794a4cc0bSNuno Antunes bcopy(curthread->td_comm, arg, len + 1); 53894a4cc0bSNuno Antunes kprintf("%s: Sending message.\en", curthread->td_comm); 53994a4cc0bSNuno Antunes my_service_queue(arg); 54094a4cc0bSNuno Antunes} 54194a4cc0bSNuno Antunes.Ed 54294a4cc0bSNuno Antunes.Sh NOTES 54394a4cc0bSNuno AntunesAll the default putport handlers (used when a message is sent) currently 544*c6e8b6c1SSascha Wildnerimplement asynchronous putports only, i.e.\& all *_putport() handlers return 54594a4cc0bSNuno Antunes.Er EASYNC . 54694a4cc0bSNuno AntunesYou can still have synchronous putport handlers (which are run in the sender's 54794a4cc0bSNuno Antunescontext) but you have to implement the function yourself and then override the 54894a4cc0bSNuno Antunesdefault. 54994a4cc0bSNuno Antunes.Pp 55094a4cc0bSNuno AntunesPort handler functions can be overridden with custom functions if required. 55194a4cc0bSNuno AntunesYou can override the default putport handler by either using the 55294a4cc0bSNuno Antunes.Fn lwkt_initport_putonly 55394a4cc0bSNuno Antunesinitializer, or by manipulating the mp_putport handler pointer directly on the 55494a4cc0bSNuno Antuneslwkt_port structure. 55594a4cc0bSNuno Antunes.Pp 55694a4cc0bSNuno AntunesThere is one such case where the putport handler is overridden in 55794a4cc0bSNuno Antunes.Pa sys/kern/netisr.c . 55894a4cc0bSNuno AntunesIn that case, the putport handler is overridden to detect a loopback message 55994a4cc0bSNuno Antunes(when the target port belongs to the sending thread). 56094a4cc0bSNuno AntunesThis special putport handler turns the sent message into a direct function call 56194a4cc0bSNuno Antunesinstead of queueing it to the port. 56294a4cc0bSNuno Antunes.Pp 56394a4cc0bSNuno AntunesThe 56494a4cc0bSNuno Antunes.Fn lwkt_replymsg 565*c6e8b6c1SSascha Wildnerfunction works differently depending on the original message request. 566*c6e8b6c1SSascha WildnerIf the 56794a4cc0bSNuno Antunesmessage was originally an asynchronous request, the reply will be queued to the 568*c6e8b6c1SSascha Wildnersender's reply port. 569*c6e8b6c1SSascha WildnerIf the message was originally a synchronous request, then 57094a4cc0bSNuno Antunesthis function will just write the error response on the message and wake up the 57194a4cc0bSNuno Antuneswaiter without queueing the message to the reply port. 57294a4cc0bSNuno AntunesThere is no need to queue in the synchronous request case because the original 57394a4cc0bSNuno Antunessender had blocked waiting on this specific message with 57494a4cc0bSNuno Antunes.Fn lwkt_domsg . 57594a4cc0bSNuno Antunes.Pp 57694a4cc0bSNuno AntunesAs is the case with putport handler, the replyport handler can also be 57794a4cc0bSNuno Antunesoverridden. 57894a4cc0bSNuno AntunesYou override the default replyport handler by using the 57994a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly 58094a4cc0bSNuno Antunesor the 58194a4cc0bSNuno Antunes.Fn lwkt_initport_replyonly_null 58294a4cc0bSNuno Antunesport initializers, or by manipulating the mp_replyport handler pointer directly 58394a4cc0bSNuno Antuneson the lwkt_port structure. 58494a4cc0bSNuno Antunes.Pp 58594a4cc0bSNuno AntunesThe sent message structure is reused for replies. 58694a4cc0bSNuno AntunesWhen a message is replied to, the error response is written on the message 58794a4cc0bSNuno Antuneswhich is subsequently sent to the reply port. 58894a4cc0bSNuno Antunes.Sh SEE ALSO 58994a4cc0bSNuno Antunes.Xr serializer 9 , 59094a4cc0bSNuno Antunes.Xr spinlock 9 59194a4cc0bSNuno Antunes.Sh HISTORY 59294a4cc0bSNuno AntunesThe LWKT msgport interface first appeared in 59394a4cc0bSNuno Antunes.Dx 1.0 . 59494a4cc0bSNuno Antunes.Sh AUTHORS 59594a4cc0bSNuno Antunes.An -nosplit 59694a4cc0bSNuno AntunesThe 59794a4cc0bSNuno Antunes.Nm msgport 59894a4cc0bSNuno Antunesmessage passing interface implementation was written by 59994a4cc0bSNuno Antunes.An Matthew Dillon . 60094a4cc0bSNuno AntunesThis manual page was written by 60194a4cc0bSNuno Antunes.An Nuno Antunes . 602