0193f6f6209ccd3c8e0dbe208683645d9b7b981f
[dragonfly.git] / sys / kern / kern_sysmsg.c
1 /*
2  * Copyright (c) 2003,2004 Matthew Dillon <dillon@backplane.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $DragonFly: src/sys/kern/Attic/kern_sysmsg.c,v 1.1 2004/06/04 20:35:36 dillon Exp $
27  */
28
29 /*
30  * SYSMSG is our system call message encapsulation and handling subsystem.
31  * System calls are now encapsulated in messages.  A system call can execute
32  * synchronously or asynchronously.  If a system call wishes to run 
33  * asynchronously it returns EASYNC and the process records the pending system
34  * call message in p_sysmsgq.
35  *
36  * SYSMSGs work similarly to LWKT messages in that the originator can request
37  * a synchronous or asynchronous operation in isolation from the actual system
38  * call which can choose to run the system call synchronous or asynchronously
39  * (independant of what was requested).  Like LWKT messages, the synchronous
40  * path avoids all queueing operations and is almost as fast as making a 
41  * direct procedure call.
42  */
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/proc.h>
47 #include <sys/pioctl.h>
48 #include <sys/kernel.h>
49 #include <sys/resourcevar.h>
50 #include <sys/signalvar.h>
51 #include <sys/syscall.h>
52 #include <sys/sysctl.h>
53 #include <sys/sysent.h>
54 #include <sys/uio.h>
55 #include <sys/vmmeter.h>
56 #include <sys/malloc.h>
57 #ifdef KTRACE
58 #include <sys/ktrace.h>
59 #endif
60 #include <sys/upcall.h>
61 #include <sys/sysproto.h>
62 #include <sys/sysunion.h>
63
64 #include <vm/vm.h>
65 #include <vm/vm_param.h>
66 #include <sys/lock.h>
67 #include <vm/pmap.h>
68 #include <vm/vm_kern.h>
69 #include <vm/vm_map.h>
70 #include <vm/vm_page.h>
71 #include <vm/vm_extern.h>
72
73 #include <sys/msgport2.h>
74 #include <sys/thread2.h>
75
76 /*
77  * Wait for a system call message to be returned.  If NULL is passed we
78  * wait for the next ready sysmsg and return it.  We return NULL if there
79  * are no pending sysmsgs queued.
80  *
81  * NOTE: proc must be curproc.
82  */
83 struct sysmsg *
84 sysmsg_wait(struct proc *p, struct sysmsg *sysmsg, int nonblock)
85 {
86         thread_t td = p->p_thread;
87
88         /*
89          * Get the next finished system call or the specified system call,
90          * blocking until it is finished (if requested).
91          */
92         if (sysmsg == NULL) {
93                 if (TAILQ_FIRST(&p->p_sysmsgq) == NULL)
94                         return(NULL);
95                 if (nonblock) {
96                         if ((sysmsg = lwkt_getport(&td->td_msgport)) == NULL)
97                                 return(NULL);
98                 } else {
99                         sysmsg = lwkt_waitport(&td->td_msgport, NULL);
100                 }
101         } else {
102                 if (nonblock && !lwkt_checkmsg(&sysmsg->lmsg))
103                         return(NULL);
104                 lwkt_waitport(&td->td_msgport, &sysmsg->lmsg);
105         }
106
107         /*
108          * sysmsg is not NULL here
109          */
110         TAILQ_REMOVE(&p->p_sysmsgq, sysmsg, msgq);
111         return(sysmsg);
112 }
113
114 /*
115  * Wait for all pending asynchronous system calls to complete, aborting them
116  * if requested (XXX).
117  */
118 void
119 sysmsg_rundown(struct proc *p, int doabort)
120 {
121         struct sysmsg *sysmsg;
122         thread_t td = p->p_thread;
123         globaldata_t gd = td->td_gd;
124
125         while (TAILQ_FIRST(&p->p_sysmsgq) != NULL) {
126                 printf("WAITSYSMSG\n");
127                 sysmsg = sysmsg_wait(p, NULL, 0);
128                 printf("WAITSYSMSG %p\n", sysmsg);
129                 KKASSERT(sysmsg != NULL);
130                 /* XXX don't bother with pending copyouts */
131                 /* XXX we really should do pending copyouts */
132                 crit_enter_quick(td);
133                 sysmsg->lmsg.opaque.ms_sysunnext = gd->gd_freesysun;
134                 gd->gd_freesysun = (void *)sysmsg;
135                 crit_exit_quick(td);
136         }
137 }
138