libexec exec fix
[minix.git] / servers / vfs / comm.c
blob41760827fc6d007377d228a088ddacffa23c0ef1
1 #include "fs.h"
2 #include "glo.h"
3 #include "vmnt.h"
4 #include "fproc.h"
5 #include <minix/vfsif.h>
6 #include <assert.h>
8 static int sendmsg(struct vmnt *vmp, struct worker_thread *wp);
9 static int queuemsg(struct vmnt *vmp);
11 /*===========================================================================*
12 * sendmsg *
13 *===========================================================================*/
14 static int sendmsg(struct vmnt *vmp, struct worker_thread *wp)
16 /* This is the low level function that sends requests to FS processes.
18 int r, transid;
20 vmp->m_comm.c_cur_reqs++; /* One more request awaiting a reply */
21 transid = wp->w_tid + VFS_TRANSID;
22 wp->w_fs_sendrec->m_type = TRNS_ADD_ID(wp->w_fs_sendrec->m_type, transid);
23 wp->w_task = vmp->m_fs_e;
24 if ((r = asynsend3(vmp->m_fs_e, wp->w_fs_sendrec, AMF_NOREPLY)) != OK) {
25 printf("VFS: sendmsg: error sending message. "
26 "FS_e: %d req_nr: %d err: %d\n", vmp->m_fs_e,
27 wp->w_fs_sendrec->m_type, r);
28 util_stacktrace();
29 return(r);
32 return(r);
35 /*===========================================================================*
36 * send_work *
37 *===========================================================================*/
38 void send_work(void)
40 /* Try to send out as many requests as possible */
41 struct vmnt *vmp;
43 if (sending == 0) return;
44 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
45 fs_sendmore(vmp);
48 /*===========================================================================*
49 * fs_cancel *
50 *===========================================================================*/
51 void fs_cancel(struct vmnt *vmp)
53 /* Cancel all pending requests for this vmp */
54 struct worker_thread *worker;
56 while ((worker = vmp->m_comm.c_req_queue) != NULL) {
57 vmp->m_comm.c_req_queue = worker->w_next;
58 worker->w_next = NULL;
59 sending--;
60 worker_stop(worker);
64 /*===========================================================================*
65 * fs_sendmore *
66 *===========================================================================*/
67 void fs_sendmore(struct vmnt *vmp)
69 struct worker_thread *worker;
71 /* Can we send more requests? */
72 if (vmp->m_fs_e == NONE) return;
73 if ((worker = vmp->m_comm.c_req_queue) == NULL) /* No process is queued */
74 return;
75 if (vmp->m_comm.c_cur_reqs >= vmp->m_comm.c_max_reqs)/*No room to send more*/
76 return;
77 if (vmp->m_flags & VMNT_CALLBACK) /* Hold off for now */
78 return;
80 vmp->m_comm.c_req_queue = worker->w_next; /* Remove head */
81 worker->w_next = NULL;
82 sending--;
83 assert(sending >= 0);
84 (void) sendmsg(vmp, worker);
87 /*===========================================================================*
88 * drv_sendrec *
89 *===========================================================================*/
90 int drv_sendrec(endpoint_t drv_e, message *reqmp)
92 int r;
93 struct dmap *dp;
95 if ((dp = get_dmap(drv_e)) == NULL)
96 panic("driver endpoint %d invalid", drv_e);
98 lock_dmap(dp);
99 if (dp->dmap_servicing != NONE)
100 panic("driver locking inconsistency");
101 dp->dmap_servicing = self->w_tid;
102 self->w_task = drv_e;
103 self->w_drv_sendrec = reqmp;
105 if ((r = asynsend3(drv_e, self->w_drv_sendrec, AMF_NOREPLY)) == OK) {
106 /* Yield execution until we've received the reply */
107 worker_wait();
108 } else {
109 printf("VFS: drv_sendrec: error sending msg to driver %d: %d\n",
110 drv_e, r);
111 util_stacktrace();
114 dp->dmap_servicing = NONE;
115 self->w_task = NONE;
116 self->w_drv_sendrec = NULL;
117 unlock_dmap(dp);
118 return(OK);
121 /*===========================================================================*
122 * fs_sendrec *
123 *===========================================================================*/
124 int fs_sendrec(endpoint_t fs_e, message *reqmp)
126 struct vmnt *vmp;
127 int r;
129 if ((vmp = find_vmnt(fs_e)) == NULL) {
130 printf("Trying to talk to non-existent FS endpoint %d\n", fs_e);
131 return(EIO);
133 if (fs_e == fp->fp_endpoint) return(EDEADLK);
135 self->w_fs_sendrec = reqmp; /* Where to store request and reply */
137 /* Find out whether we can send right away or have to enqueue */
138 if ( !(vmp->m_flags & VMNT_CALLBACK) &&
139 vmp->m_comm.c_cur_reqs < vmp->m_comm.c_max_reqs) {
140 /* There's still room to send more and no proc is queued */
141 r = sendmsg(vmp, self);
142 } else {
143 r = queuemsg(vmp);
145 self->w_next = NULL; /* End of list */
147 if (r != OK) return(r);
149 worker_wait(); /* Yield execution until we've received the reply. */
151 return(reqmp->m_type);
154 /*===========================================================================*
155 * queuemsg *
156 *===========================================================================*/
157 static int queuemsg(struct vmnt *vmp)
159 /* Put request on queue for vmnt */
161 struct worker_thread *queue;
163 if (vmp->m_comm.c_req_queue == NULL) {
164 vmp->m_comm.c_req_queue = self;
165 } else {
166 /* Walk the list ... */
167 queue = vmp->m_comm.c_req_queue;
168 while (queue->w_next != NULL) queue = queue->w_next;
170 /* ... and append this worker */
171 queue->w_next = self;
174 self->w_next = NULL; /* End of list */
175 sending++;
177 return(OK);