2 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * NOTE! This file may be compiled for userland libraries as well as for
37 * $DragonFly: src/sys/kern/lwkt_msgport.c,v 1.41 2007/05/24 05:51:27 dillon Exp $
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/rtprio.h>
47 #include <sys/queue.h>
48 #include <sys/sysctl.h>
49 #include <sys/kthread.h>
50 #include <sys/signalvar.h>
51 #include <sys/signal2.h>
52 #include <machine/cpu.h>
56 #include <vm/vm_param.h>
57 #include <vm/vm_kern.h>
58 #include <vm/vm_object.h>
59 #include <vm/vm_page.h>
60 #include <vm/vm_map.h>
61 #include <vm/vm_pager.h>
62 #include <vm/vm_extern.h>
63 #include <vm/vm_zone.h>
65 #include <sys/thread2.h>
66 #include <sys/msgport2.h>
67 #include <sys/spinlock2.h>
69 #include <machine/stdarg.h>
70 #include <machine/cpufunc.h>
72 #include <machine/smp.h>
75 #include <sys/malloc.h>
76 MALLOC_DEFINE(M_LWKTMSG, "lwkt message", "lwkt message");
80 #include <sys/stdint.h>
81 #include <libcaps/thread.h>
82 #include <sys/thread.h>
83 #include <sys/msgport.h>
84 #include <sys/errno.h>
85 #include <libcaps/globaldata.h>
86 #include <machine/cpufunc.h>
87 #include <sys/thread2.h>
88 #include <sys/msgport2.h>
94 /************************************************************************
96 ************************************************************************/
101 * Request asynchronous completion and call lwkt_beginmsg(). The
102 * target port can opt to execute the message synchronously or
103 * asynchronously and this function will automatically queue the
104 * response if the target executes the message synchronously.
106 * NOTE: The message is in an indeterminant state until this call
107 * returns. The caller should not mess with it (e.g. try to abort it)
111 lwkt_sendmsg(lwkt_port_t port, lwkt_msg_t msg)
115 KKASSERT(msg->ms_reply_port != NULL &&
116 (msg->ms_flags & (MSGF_DONE|MSGF_QUEUED)) == MSGF_DONE);
117 msg->ms_flags &= ~(MSGF_REPLY | MSGF_SYNC | MSGF_DONE);
118 if ((error = lwkt_beginmsg(port, msg)) != EASYNC) {
119 lwkt_replymsg(msg, error);
126 * Request asynchronous completion and call lwkt_beginmsg(). The
127 * target port can opt to execute the message synchronously or
128 * asynchronously and this function will automatically queue the
129 * response if the target executes the message synchronously.
132 lwkt_domsg(lwkt_port_t port, lwkt_msg_t msg)
136 KKASSERT(msg->ms_reply_port != NULL &&
137 (msg->ms_flags & (MSGF_DONE|MSGF_QUEUED)) == MSGF_DONE);
138 msg->ms_flags &= ~(MSGF_REPLY | MSGF_DONE);
139 msg->ms_flags |= MSGF_SYNC;
140 if ((error = lwkt_beginmsg(port, msg)) == EASYNC) {
141 error = lwkt_waitmsg(msg);
143 msg->ms_flags |= MSGF_DONE | MSGF_REPLY;
151 * Forward a message received on one port to another port.
154 lwkt_forwardmsg(lwkt_port_t port, lwkt_msg_t msg)
159 KKASSERT((msg->ms_flags & (MSGF_QUEUED|MSGF_DONE|MSGF_REPLY)) == 0);
160 if ((error = port->mp_putport(port, msg)) != EASYNC)
161 lwkt_replymsg(msg, error);
169 * Attempt to abort a message. This only works if MSGF_ABORTABLE is set.
170 * The caller must ensure that the message will not be both replied AND
171 * destroyed while the abort is in progress.
173 * This function issues a callback which might block!
176 lwkt_abortmsg(lwkt_msg_t msg)
179 * A critical section protects us from reply IPIs on this cpu.
184 * Shortcut the operation if the message has already been returned.
185 * The callback typically constructs a lwkt_msg with the abort request,
186 * issues it synchronously, and waits for completion. The callback
187 * is not required to actually abort the message and the target port,
188 * upon receiving an abort request message generated by the callback
189 * should check whether the original message has already completed or
192 if (msg->ms_flags & MSGF_ABORTABLE) {
193 if ((msg->ms_flags & (MSGF_DONE|MSGF_REPLY)) == 0)
194 msg->ms_abortfn(msg);
199 /************************************************************************
200 * PORT INITIALIZATION API *
201 ************************************************************************/
203 static void *lwkt_thread_getport(lwkt_port_t port);
204 static int lwkt_thread_putport(lwkt_port_t port, lwkt_msg_t msg);
205 static void *lwkt_thread_waitport(lwkt_port_t port, lwkt_msg_t msg);
206 static void lwkt_thread_replyport(lwkt_port_t port, lwkt_msg_t msg);
208 static void *lwkt_spin_getport(lwkt_port_t port);
209 static int lwkt_spin_putport(lwkt_port_t port, lwkt_msg_t msg);
210 static void *lwkt_spin_waitport(lwkt_port_t port, lwkt_msg_t msg);
211 static void lwkt_spin_replyport(lwkt_port_t port, lwkt_msg_t msg);
213 static void lwkt_null_replyport(lwkt_port_t port, lwkt_msg_t msg);
214 static void *lwkt_panic_getport(lwkt_port_t port);
215 static int lwkt_panic_putport(lwkt_port_t port, lwkt_msg_t msg);
216 static void *lwkt_panic_waitport(lwkt_port_t port, lwkt_msg_t msg);
217 static void lwkt_panic_replyport(lwkt_port_t port, lwkt_msg_t msg);
220 * Core port initialization (internal)
224 _lwkt_initport(lwkt_port_t port,
225 void *(*gportfn)(lwkt_port_t),
226 int (*pportfn)(lwkt_port_t, lwkt_msg_t),
227 void *(*wportfn)(lwkt_port_t, lwkt_msg_t),
228 void (*rportfn)(lwkt_port_t, lwkt_msg_t))
230 bzero(port, sizeof(*port));
231 TAILQ_INIT(&port->mp_msgq);
232 port->mp_getport = gportfn;
233 port->mp_putport = pportfn;
234 port->mp_waitport = wportfn;
235 port->mp_replyport = rportfn;
239 * lwkt_initport_thread()
241 * Initialize a port for use by a particular thread. The port may
242 * only be used by <td>.
245 lwkt_initport_thread(lwkt_port_t port, thread_t td)
250 lwkt_thread_waitport,
251 lwkt_thread_replyport);
256 * lwkt_initport_spin()
258 * Initialize a port for use with descriptors that might be accessed
259 * via multiple LWPs, processes, or threads. Has somewhat more
260 * overhead then thread ports.
263 lwkt_initport_spin(lwkt_port_t port)
269 lwkt_spin_replyport);
270 spin_init(&port->mpu_spin);
274 * Similar to the standard initport, this function simply marks the message
275 * as being done and does not attempt to return it to an originating port.
278 lwkt_initport_replyonly_null(lwkt_port_t port)
284 lwkt_null_replyport);
288 * Initialize a reply-only port, typically used as a message sink. Such
289 * ports can only be used as a reply port.
292 lwkt_initport_replyonly(lwkt_port_t port,
293 void (*rportfn)(lwkt_port_t, lwkt_msg_t))
295 _lwkt_initport(port, lwkt_panic_getport, lwkt_panic_putport,
296 lwkt_panic_waitport, rportfn);
300 lwkt_initport_putonly(lwkt_port_t port,
301 int (*pportfn)(lwkt_port_t, lwkt_msg_t))
303 _lwkt_initport(port, lwkt_panic_getport, pportfn,
304 lwkt_panic_waitport, lwkt_panic_replyport);
308 lwkt_initport_panic(lwkt_port_t port)
314 lwkt_panic_replyport);
320 * Retrieve the next message from the port's message queue, return NULL
321 * if no messages are pending. The retrieved message will either be a
322 * request or a reply based on the MSGF_REPLY bit.
324 * The calling thread MUST own the port.
329 _lwkt_pullmsg(lwkt_port_t port, lwkt_msg_t msg)
332 * normal case, remove and return the message.
334 TAILQ_REMOVE(&port->mp_msgq, msg, ms_node);
335 msg->ms_flags &= ~MSGF_QUEUED;
338 /************************************************************************
339 * THREAD PORT BACKEND *
340 ************************************************************************
342 * This backend is used when the port a message is retrieved from is owned
343 * by a single thread (the calling thread). Messages are IPId to the
344 * correct cpu before being enqueued to a port. Note that this is fairly
345 * optimal since scheduling would have had to do an IPI anyway if the
346 * message were headed to a different cpu.
352 * This function completes reply processing for the default case in the
353 * context of the originating cpu.
357 lwkt_thread_replyport_remote(lwkt_msg_t msg)
359 lwkt_port_t port = msg->ms_reply_port;
362 * Chase any thread migration that occurs
364 if (port->mpu_td->td_gd != mycpu) {
365 lwkt_send_ipiq(port->mpu_td->td_gd,
366 (ipifunc1_t)lwkt_thread_replyport_remote, msg);
374 KKASSERT(msg->ms_flags & MSGF_INTRANSIT);
375 msg->ms_flags &= ~MSGF_INTRANSIT;
377 if (msg->ms_flags & MSGF_SYNC) {
378 msg->ms_flags |= MSGF_REPLY | MSGF_DONE;
380 TAILQ_INSERT_TAIL(&port->mp_msgq, msg, ms_node);
381 msg->ms_flags |= MSGF_REPLY | MSGF_DONE | MSGF_QUEUED;
383 if (port->mp_flags & MSGPORTF_WAITING)
384 lwkt_schedule(port->mpu_td);
390 * lwkt_thread_replyport() - Backend to lwkt_replymsg()
392 * Called with the reply port as an argument but in the context of the
393 * original target port. Completion must occur on the target port's
396 * The critical section protects us from IPIs on the this CPU.
399 lwkt_thread_replyport(lwkt_port_t port, lwkt_msg_t msg)
401 KKASSERT((msg->ms_flags & (MSGF_DONE|MSGF_QUEUED)) == 0);
403 if (msg->ms_flags & MSGF_SYNC) {
405 * If a synchronous completion has been requested, just wakeup
406 * the message without bothering to queue it to the target port.
408 * Assume the target thread is non-preemptive, so no critical
409 * section is required.
412 if (port->mpu_td->td_gd == mycpu) {
414 msg->ms_flags |= MSGF_DONE | MSGF_REPLY;
415 if (port->mp_flags & MSGPORTF_WAITING)
416 lwkt_schedule(port->mpu_td);
420 msg->ms_flags |= MSGF_INTRANSIT;
422 msg->ms_flags |= MSGF_REPLY;
423 lwkt_send_ipiq(port->mpu_td->td_gd,
424 (ipifunc1_t)lwkt_thread_replyport_remote, msg);
429 * If an asynchronous completion has been requested the message
430 * must be queued to the reply port. MSGF_REPLY cannot be set
431 * until the message actually gets queued.
433 * A critical section is required to interlock the port queue.
436 if (port->mpu_td->td_gd == mycpu) {
439 TAILQ_INSERT_TAIL(&port->mp_msgq, msg, ms_node);
440 msg->ms_flags |= MSGF_REPLY | MSGF_DONE | MSGF_QUEUED;
441 if (port->mp_flags & MSGPORTF_WAITING)
442 lwkt_schedule(port->mpu_td);
447 msg->ms_flags |= MSGF_INTRANSIT;
449 msg->ms_flags |= MSGF_REPLY;
450 lwkt_send_ipiq(port->mpu_td->td_gd,
451 (ipifunc1_t)lwkt_thread_replyport_remote, msg);
458 * lwkt_thread_putport() - Backend to lwkt_beginmsg()
460 * Called with the target port as an argument but in the context of the
461 * reply port. This function always implements an asynchronous put to
462 * the target message port, and thus returns EASYNC.
464 * The message must already have cleared MSGF_DONE and MSGF_REPLY
471 lwkt_thread_putport_remote(lwkt_msg_t msg)
473 lwkt_port_t port = msg->ms_target_port;
476 * Chase any thread migration that occurs
478 if (port->mpu_td->td_gd != mycpu) {
479 lwkt_send_ipiq(port->mpu_td->td_gd,
480 (ipifunc1_t)lwkt_thread_putport_remote, msg);
488 KKASSERT(msg->ms_flags & MSGF_INTRANSIT);
489 msg->ms_flags &= ~MSGF_INTRANSIT;
491 TAILQ_INSERT_TAIL(&port->mp_msgq, msg, ms_node);
492 msg->ms_flags |= MSGF_QUEUED;
493 if (port->mp_flags & MSGPORTF_WAITING)
494 lwkt_schedule(port->mpu_td);
501 lwkt_thread_putport(lwkt_port_t port, lwkt_msg_t msg)
503 KKASSERT((msg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0);
505 msg->ms_target_port = port;
507 if (port->mpu_td->td_gd == mycpu) {
510 msg->ms_flags |= MSGF_QUEUED;
511 TAILQ_INSERT_TAIL(&port->mp_msgq, msg, ms_node);
512 if (port->mp_flags & MSGPORTF_WAITING)
513 lwkt_schedule(port->mpu_td);
518 msg->ms_flags |= MSGF_INTRANSIT;
520 lwkt_send_ipiq(port->mpu_td->td_gd,
521 (ipifunc1_t)lwkt_thread_putport_remote, msg);
528 * lwkt_thread_getport()
530 * Retrieve the next message from the port or NULL if no messages
534 lwkt_thread_getport(lwkt_port_t port)
538 KKASSERT(port->mpu_td == curthread);
540 crit_enter_quick(port->mpu_td);
541 if ((msg = TAILQ_FIRST(&port->mp_msgq)) != NULL)
542 _lwkt_pullmsg(port, msg);
543 crit_exit_quick(port->mpu_td);
548 * lwkt_thread_waitport()
550 * If msg is NULL, dequeue the next message from the port's message
551 * queue, block until a message is ready. This function never
554 * If msg is non-NULL, block until the requested message has been
555 * replied, then dequeue and return it.
557 * NOTE: This function should not be used to wait for specific
558 * incoming requests because MSGF_DONE only applies to replies.
560 * Note that the API does not currently support multiple threads waiting
561 * on a single port. The port must be owned by the caller.
564 lwkt_thread_waitport(lwkt_port_t port, lwkt_msg_t msg)
566 thread_t td = curthread;
569 KKASSERT(port->mpu_td == td);
570 crit_enter_quick(td);
573 * Wait for any message
575 if ((msg = TAILQ_FIRST(&port->mp_msgq)) == NULL) {
576 port->mp_flags |= MSGPORTF_WAITING;
577 td->td_flags |= TDF_BLOCKED;
579 lwkt_deschedule_self(td);
581 } while ((msg = TAILQ_FIRST(&port->mp_msgq)) == NULL);
582 td->td_flags &= ~TDF_BLOCKED;
583 port->mp_flags &= ~MSGPORTF_WAITING;
585 _lwkt_pullmsg(port, msg);
588 * Wait for a specific message.
590 KKASSERT(msg->ms_reply_port == port);
591 if ((msg->ms_flags & MSGF_DONE) == 0) {
593 while ((msg->ms_flags & MSGF_DONE) == 0) {
595 * MSGF_PCATCH is only set by processes which wish to
596 * abort the message they are blocked on when a signal
597 * occurs. Note that we still must wait for message
598 * completion after sending an abort request.
600 if (msg->ms_flags & MSGF_PCATCH) {
601 if (sentabort == 0 && CURSIG(port->mpu_td->td_lwp)) {
609 * XXX set TDF_SINTR so 'ps' knows the difference between
610 * an interruptable wait and a disk wait. YYY eventually
611 * move LWP_SINTR to TDF_SINTR to reduce duplication.
613 port->mp_flags |= MSGPORTF_WAITING;
614 td->td_flags |= TDF_SINTR | TDF_BLOCKED;
615 lwkt_deschedule_self(td);
617 td->td_flags &= ~(TDF_SINTR | TDF_BLOCKED);
618 port->mp_flags &= ~MSGPORTF_WAITING;
623 * Once the MSGF_DONE bit is set, the message is stable. We
624 * can just check MSGF_QUEUED to determine
626 if (msg->ms_flags & MSGF_QUEUED)
627 _lwkt_pullmsg(port, msg);
633 /************************************************************************
634 * SPIN PORT BACKEND *
635 ************************************************************************
637 * This backend uses spinlocks instead of making assumptions about which
638 * thread is accessing the port. It must be used when a port is not owned
639 * by a particular thread. This is less optimal then thread ports but
640 * you don't have a choice if there are multiple threads accessing the port.
645 lwkt_spin_getport(lwkt_port_t port)
649 spin_lock_wr(&port->mpu_spin);
650 if ((msg = TAILQ_FIRST(&port->mp_msgq)) != NULL)
651 _lwkt_pullmsg(port, msg);
652 spin_unlock_wr(&port->mpu_spin);
658 lwkt_spin_putport(lwkt_port_t port, lwkt_msg_t msg)
662 KKASSERT((msg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0);
664 msg->ms_target_port = port;
665 spin_lock_wr(&port->mpu_spin);
666 msg->ms_flags |= MSGF_QUEUED;
667 TAILQ_INSERT_TAIL(&port->mp_msgq, msg, ms_node);
669 if (port->mp_flags & MSGPORTF_WAITING) {
670 port->mp_flags &= ~MSGPORTF_WAITING;
673 spin_unlock_wr(&port->mpu_spin);
681 lwkt_spin_waitport(lwkt_port_t port, lwkt_msg_t msg)
686 spin_lock_wr(&port->mpu_spin);
689 * Wait for any message
691 while ((msg = TAILQ_FIRST(&port->mp_msgq)) == NULL) {
692 port->mp_flags |= MSGPORTF_WAITING;
693 msleep(port, &port->mpu_spin, 0, "wport", 0);
694 /* see note at the top on the MSGPORTF_WAITING flag */
696 _lwkt_pullmsg(port, msg);
699 * Wait for a specific message.
701 KKASSERT(msg->ms_reply_port == port);
702 if ((msg->ms_flags & MSGF_DONE) == 0) {
704 while ((msg->ms_flags & MSGF_DONE) == 0) {
708 * If message was sent synchronously from the beginning
709 * the wakeup will be on the message structure, else it
710 * will be on the port structure.
712 if (msg->ms_flags & MSGF_SYNC) {
716 port->mp_flags |= MSGPORTF_WAITING;
720 * MSGF_PCATCH is only set by processes which wish to
721 * abort the message they are blocked on when a signal
722 * occurs. Note that we still must wait for message
723 * completion after sending an abort request.
725 * XXX ERESTART not handled.
727 if ((msg->ms_flags & MSGF_PCATCH) && sentabort == 0) {
728 error = msleep(won, &port->mpu_spin, PCATCH, "wmsg", 0);
731 spin_unlock_wr(&port->mpu_spin);
733 spin_lock_wr(&port->mpu_spin);
736 error = msleep(won, &port->mpu_spin, 0, "wmsg", 0);
738 /* see note at the top on the MSGPORTF_WAITING flag */
741 * Turn EINTR into ERESTART if the signal indicates.
743 if (sentabort && msg->ms_error == EINTR)
744 msg->ms_error = sentabort;
747 * Once the MSGF_DONE bit is set, the message is stable. We
748 * can just check MSGF_QUEUED to determine
750 if (msg->ms_flags & MSGF_QUEUED)
751 _lwkt_pullmsg(port, msg);
754 spin_unlock_wr(&port->mpu_spin);
760 lwkt_spin_replyport(lwkt_port_t port, lwkt_msg_t msg)
764 KKASSERT((msg->ms_flags & (MSGF_DONE|MSGF_QUEUED)) == 0);
766 if (msg->ms_flags & MSGF_SYNC) {
768 * If a synchronous completion has been requested, just wakeup
769 * the message without bothering to queue it to the target port.
771 msg->ms_flags |= MSGF_DONE | MSGF_REPLY;
775 * If an asynchronous completion has been requested the message
776 * must be queued to the reply port. MSGF_REPLY cannot be set
777 * until the message actually gets queued.
779 spin_lock_wr(&port->mpu_spin);
780 TAILQ_INSERT_TAIL(&port->mp_msgq, msg, ms_node);
781 msg->ms_flags |= MSGF_REPLY | MSGF_DONE | MSGF_QUEUED;
783 if (port->mp_flags & MSGPORTF_WAITING) {
784 port->mp_flags &= ~MSGPORTF_WAITING;
787 spin_unlock_wr(&port->mpu_spin);
793 /************************************************************************
794 * PANIC AND SPECIAL PORT FUNCTIONS *
795 ************************************************************************/
798 * You can point a port's reply vector at this function if you just want
799 * the message marked done, without any queueing or signaling. This is
800 * often used for structure-embedded messages.
804 lwkt_null_replyport(lwkt_port_t port, lwkt_msg_t msg)
806 msg->ms_flags |= MSGF_DONE | MSGF_REPLY;
811 lwkt_panic_getport(lwkt_port_t port)
813 panic("lwkt_getport() illegal on port %p", port);
818 lwkt_panic_putport(lwkt_port_t port, lwkt_msg_t msg)
820 panic("lwkt_begin/do/sendmsg() illegal on port %p msg %p", port, msg);
825 lwkt_panic_waitport(lwkt_port_t port, lwkt_msg_t msg)
827 panic("port %p cannot be waited on msg %p", port, msg);
832 lwkt_panic_replyport(lwkt_port_t port, lwkt_msg_t msg)
834 panic("lwkt_replymsg() is illegal on port %p msg %p", port, msg);