tools/llvm: Do not build with symbols
[minix3.git] / minix / servers / vfs / comm.c
blob663caebb24fe35707ce395abc73f4d0a1a0259bd
1 #include "fs.h"
2 #include <minix/vfsif.h>
3 #include <assert.h>
4 #include <string.h>
6 static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp);
7 static int queuemsg(struct vmnt *vmp);
9 /*===========================================================================*
10 * sendmsg *
11 *===========================================================================*/
12 static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp)
14 /* This is the low level function that sends requests.
15 * Currently to FSes or VM.
17 int r, transid;
19 if(vmp) vmp->m_comm.c_cur_reqs++; /* One more request awaiting a reply */
20 transid = wp->w_tid + VFS_TRANSID;
21 wp->w_sendrec->m_type = TRNS_ADD_ID(wp->w_sendrec->m_type, transid);
22 wp->w_task = dst;
23 if ((r = asynsend3(dst, wp->w_sendrec, AMF_NOREPLY)) != OK) {
24 printf("VFS: sendmsg: error sending message. "
25 "dest: %d req_nr: %d err: %d\n", dst,
26 wp->w_sendrec->m_type, r);
27 util_stacktrace();
28 return(r);
31 return(r);
34 /*===========================================================================*
35 * send_work *
36 *===========================================================================*/
37 void send_work(void)
39 /* Try to send out as many requests as possible */
40 struct vmnt *vmp;
42 if (sending == 0) return;
43 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
44 fs_sendmore(vmp);
47 /*===========================================================================*
48 * fs_cancel *
49 *===========================================================================*/
50 void fs_cancel(struct vmnt *vmp)
52 /* Cancel all pending requests for this vmp */
53 struct worker_thread *worker;
55 while ((worker = vmp->m_comm.c_req_queue) != NULL) {
56 vmp->m_comm.c_req_queue = worker->w_next;
57 worker->w_next = NULL;
58 sending--;
59 worker_stop(worker);
63 /*===========================================================================*
64 * fs_sendmore *
65 *===========================================================================*/
66 void fs_sendmore(struct vmnt *vmp)
68 struct worker_thread *worker;
70 /* Can we send more requests? */
71 if (vmp->m_fs_e == NONE) return;
72 if ((worker = vmp->m_comm.c_req_queue) == NULL) /* No process is queued */
73 return;
74 if (vmp->m_comm.c_cur_reqs >= vmp->m_comm.c_max_reqs)/*No room to send more*/
75 return;
76 if (vmp->m_flags & VMNT_CALLBACK) /* Hold off for now */
77 return;
79 vmp->m_comm.c_req_queue = worker->w_next; /* Remove head */
80 worker->w_next = NULL;
81 sending--;
82 assert(sending >= 0);
83 (void) sendmsg(vmp, vmp->m_fs_e, worker);
86 /*===========================================================================*
87 * drv_sendrec *
88 *===========================================================================*/
89 int drv_sendrec(endpoint_t drv_e, message *reqmp)
91 int r;
92 struct dmap *dp;
94 /* For the CTTY_MAJOR case, we would actually have to lock the device
95 * entry being redirected to. However, the CTTY major only hosts a
96 * character device while this function is used only for block devices.
97 * Thus, we can simply deny the request immediately.
99 if (drv_e == CTTY_ENDPT) {
100 printf("VFS: /dev/tty is not a block device!\n");
101 return EIO;
104 if ((dp = get_dmap(drv_e)) == NULL)
105 panic("driver endpoint %d invalid", drv_e);
107 lock_dmap(dp);
108 if (dp->dmap_servicing != INVALID_THREAD)
109 panic("driver locking inconsistency");
110 dp->dmap_servicing = self->w_tid;
111 self->w_task = drv_e;
112 self->w_drv_sendrec = reqmp;
114 if ((r = asynsend3(drv_e, self->w_drv_sendrec, AMF_NOREPLY)) == OK) {
115 /* Yield execution until we've received the reply */
116 worker_wait();
117 } else {
118 printf("VFS: drv_sendrec: error sending msg to driver %d: %d\n",
119 drv_e, r);
120 util_stacktrace();
123 dp->dmap_servicing = INVALID_THREAD;
124 self->w_task = NONE;
125 self->w_drv_sendrec = NULL;
126 unlock_dmap(dp);
127 return(OK);
130 /*===========================================================================*
131 * fs_sendrec *
132 *===========================================================================*/
133 int fs_sendrec(endpoint_t fs_e, message *reqmp)
135 struct vmnt *vmp;
136 int r;
138 if ((vmp = find_vmnt(fs_e)) == NULL) {
139 printf("Trying to talk to non-existent FS endpoint %d\n", fs_e);
140 return(EIO);
142 if (fs_e == fp->fp_endpoint) return(EDEADLK);
144 self->w_sendrec = reqmp; /* Where to store request and reply */
146 /* Find out whether we can send right away or have to enqueue */
147 if ( !(vmp->m_flags & VMNT_CALLBACK) &&
148 vmp->m_comm.c_cur_reqs < vmp->m_comm.c_max_reqs) {
149 /* There's still room to send more and no proc is queued */
150 r = sendmsg(vmp, vmp->m_fs_e, self);
151 } else {
152 r = queuemsg(vmp);
154 self->w_next = NULL; /* End of list */
156 if (r != OK) return(r);
158 worker_wait(); /* Yield execution until we've received the reply. */
160 return(reqmp->m_type);
163 /*===========================================================================*
164 * vm_sendrec *
165 *===========================================================================*/
166 int vm_sendrec(message *reqmp)
168 int r;
170 assert(self);
171 assert(reqmp);
173 self->w_sendrec = reqmp; /* Where to store request and reply */
175 r = sendmsg(NULL, VM_PROC_NR, self);
177 self->w_next = NULL; /* End of list */
179 if (r != OK) return(r);
181 worker_wait(); /* Yield execution until we've received the reply. */
183 return(reqmp->m_type);
187 /*===========================================================================*
188 * vm_vfs_procctl_handlemem *
189 *===========================================================================*/
190 int vm_vfs_procctl_handlemem(endpoint_t ep,
191 vir_bytes mem, vir_bytes len, int flags)
193 message m;
195 /* main thread can not be suspended */
196 if(!self) return EFAULT;
198 memset(&m, 0, sizeof(m));
200 m.m_type = VM_PROCCTL;
201 m.VMPCTL_WHO = ep;
202 m.VMPCTL_PARAM = VMPPARAM_HANDLEMEM;
203 m.VMPCTL_M1 = mem;
204 m.VMPCTL_LEN = len;
205 m.VMPCTL_FLAGS = flags;
207 return vm_sendrec(&m);
210 /*===========================================================================*
211 * queuemsg *
212 *===========================================================================*/
213 static int queuemsg(struct vmnt *vmp)
215 /* Put request on queue for vmnt */
217 struct worker_thread *queue;
219 if (vmp->m_comm.c_req_queue == NULL) {
220 vmp->m_comm.c_req_queue = self;
221 } else {
222 /* Walk the list ... */
223 queue = vmp->m_comm.c_req_queue;
224 while (queue->w_next != NULL) queue = queue->w_next;
226 /* ... and append this worker */
227 queue->w_next = self;
230 self->w_next = NULL; /* End of list */
231 sending++;
233 return(OK);