Rev 1084 | Rev 1088 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1084 | Rev 1086 | ||
---|---|---|---|
Line 121... | Line 121... | ||
121 | spinlock_initialize(&phone->lock, "phone_lock"); |
121 | spinlock_initialize(&phone->lock, "phone_lock"); |
122 | phone->callee = NULL; |
122 | phone->callee = NULL; |
123 | phone->busy = 0; |
123 | phone->busy = 0; |
124 | } |
124 | } |
125 | 125 | ||
126 | /** Disconnect phone from answerbox |
- | |
127 | * |
- | |
128 | * It is allowed to call disconnect on already disconnected phone\ |
- | |
129 | */ |
- | |
130 | void ipc_phone_destroy(phone_t *phone) |
- | |
131 | { |
- | |
132 | answerbox_t *box = phone->callee; |
- | |
133 | - | ||
134 | ASSERT(box); |
- | |
135 | - | ||
136 | spinlock_lock(&phone->lock); |
- | |
137 | spinlock_lock(&box->lock); |
- | |
138 | - | ||
139 | if (phone->callee) { |
- | |
140 | list_remove(&phone->list); |
- | |
141 | phone->callee = NULL; |
- | |
142 | } |
- | |
143 | - | ||
144 | spinlock_unlock(&box->lock); |
- | |
145 | spinlock_unlock(&phone->lock); |
- | |
146 | } |
- | |
147 | - | ||
148 | /** Helper function to facilitate synchronous calls */ |
126 | /** Helper function to facilitate synchronous calls */ |
149 | void ipc_call_sync(phone_t *phone, call_t *request) |
127 | void ipc_call_sync(phone_t *phone, call_t *request) |
150 | { |
128 | { |
151 | answerbox_t sync_box; |
129 | answerbox_t sync_box; |
152 | 130 | ||
Line 188... | Line 166... | ||
188 | spinlock_unlock(&box->lock); |
166 | spinlock_unlock(&box->lock); |
189 | /* Send back answer */ |
167 | /* Send back answer */ |
190 | _ipc_answer_free_call(call); |
168 | _ipc_answer_free_call(call); |
191 | } |
169 | } |
192 | 170 | ||
- | 171 | /* Unsafe unchecking ipc_call */ |
|
- | 172 | static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) |
|
- | 173 | { |
|
- | 174 | atomic_inc(&phone->active_calls); |
|
- | 175 | call->data.phone = phone; |
|
- | 176 | ||
- | 177 | spinlock_lock(&box->lock); |
|
- | 178 | list_append(&call->list, &box->calls); |
|
- | 179 | spinlock_unlock(&box->lock); |
|
- | 180 | waitq_wakeup(&box->wq, 0); |
|
- | 181 | } |
|
- | 182 | ||
193 | /** Send a asynchronous request using phone to answerbox |
183 | /** Send a asynchronous request using phone to answerbox |
194 | * |
184 | * |
195 | * @param phone Phone connected to answerbox |
185 | * @param phone Phone connected to answerbox |
196 | * @param request Request to be sent |
186 | * @param request Request to be sent |
197 | */ |
187 | */ |
198 | void ipc_call(phone_t *phone, call_t *call) |
188 | void ipc_call(phone_t *phone, call_t *call) |
199 | { |
189 | { |
200 | answerbox_t *box; |
190 | answerbox_t *box; |
201 | 191 | ||
202 | spinlock_lock(&phone->lock); |
192 | spinlock_lock(&phone->lock); |
- | 193 | ||
203 | box = phone->callee; |
194 | box = phone->callee; |
204 | if (!box) { |
195 | if (!box) { |
205 | /* Trying to send over disconnected phone */ |
196 | /* Trying to send over disconnected phone */ |
- | 197 | spinlock_unlock(&phone->lock); |
|
- | 198 | ||
- | 199 | call->data.phone = phone; |
|
206 | IPC_SET_RETVAL(call->data, ENOENT); |
200 | IPC_SET_RETVAL(call->data, ENOENT); |
207 | _ipc_answer_free_call(call); |
201 | _ipc_answer_free_call(call); |
208 | return; |
202 | return; |
209 | } |
203 | } |
- | 204 | _ipc_call(phone, box, call); |
|
- | 205 | ||
- | 206 | spinlock_unlock(&phone->lock); |
|
- | 207 | } |
|
- | 208 | ||
- | 209 | /** Disconnect phone from answerbox |
|
- | 210 | * |
|
- | 211 | * It is allowed to call disconnect on already disconnected phone |
|
- | 212 | * |
|
- | 213 | * @return 0 - phone disconnected, -1 - the phone was already disconnected |
|
- | 214 | */ |
|
- | 215 | int ipc_phone_hangup(phone_t *phone) |
|
- | 216 | { |
|
- | 217 | answerbox_t *box; |
|
- | 218 | call_t *call; |
|
- | 219 | ||
- | 220 | spinlock_lock(&phone->lock); |
|
- | 221 | box = phone->callee; |
|
- | 222 | if (!box) { |
|
- | 223 | spinlock_unlock(&phone->lock); |
|
- | 224 | return -1; |
|
- | 225 | } |
|
210 | 226 | ||
211 | spinlock_lock(&box->lock); |
227 | spinlock_lock(&box->lock); |
212 | list_append(&call->list, &box->calls); |
228 | list_remove(&phone->list); |
- | 229 | phone->callee = NULL; |
|
213 | spinlock_unlock(&box->lock); |
230 | spinlock_unlock(&box->lock); |
- | 231 | ||
- | 232 | call = ipc_call_alloc(); |
|
- | 233 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
|
- | 234 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
|
214 | waitq_wakeup(&box->wq, 0); |
235 | _ipc_call(phone, box, call); |
- | 236 | ||
- | 237 | phone->busy = 0; |
|
215 | 238 | ||
216 | spinlock_unlock(&phone->lock); |
239 | spinlock_unlock(&phone->lock); |
- | 240 | ||
- | 241 | return 0; |
|
217 | } |
242 | } |
218 | 243 | ||
219 | /** Forwards call from one answerbox to a new one |
244 | /** Forwards call from one answerbox to a new one |
220 | * |
245 | * |
221 | * @param request Request to be forwarded |
246 | * @param request Request to be forwarded |
Line 223... | Line 248... | ||
223 | * @param oldbox Old answerbox |
248 | * @param oldbox Old answerbox |
224 | */ |
249 | */ |
225 | void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
250 | void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
226 | { |
251 | { |
227 | spinlock_lock(&oldbox->lock); |
252 | spinlock_lock(&oldbox->lock); |
- | 253 | atomic_dec(&call->data.phone->active_calls); |
|
228 | list_remove(&call->list); |
254 | list_remove(&call->list); |
229 | spinlock_unlock(&oldbox->lock); |
255 | spinlock_unlock(&oldbox->lock); |
230 | 256 | ||
231 | ipc_call(newphone, call); |
257 | ipc_call(newphone, call); |
232 | } |
258 | } |
Line 239... | Line 265... | ||
239 | */ |
265 | */ |
240 | call_t * ipc_wait_for_call(answerbox_t *box, int flags) |
266 | call_t * ipc_wait_for_call(answerbox_t *box, int flags) |
241 | { |
267 | { |
242 | call_t *request; |
268 | call_t *request; |
243 | 269 | ||
- | 270 | restart: |
|
- | 271 | if (flags & IPC_WAIT_NONBLOCKING) { |
|
- | 272 | if (waitq_sleep_timeout(&box->wq,0,1) == ESYNCH_WOULD_BLOCK) |
|
- | 273 | return NULL; |
|
- | 274 | } else |
|
- | 275 | waitq_sleep(&box->wq); |
|
- | 276 | ||
244 | spinlock_lock(&box->lock); |
277 | spinlock_lock(&box->lock); |
245 | while (1) { |
- | |
246 | if (!list_empty(&box->answers)) { |
278 | if (!list_empty(&box->answers)) { |
247 | /* Handle asynchronous answers */ |
279 | /* Handle asynchronous answers */ |
248 | request = list_get_instance(box->answers.next, call_t, list); |
280 | request = list_get_instance(box->answers.next, call_t, list); |
249 | list_remove(&request->list); |
281 | list_remove(&request->list); |
- | 282 | printf("%d %P\n", IPC_GET_METHOD(request->data), |
|
- | 283 | request->data.phone); |
|
- | 284 | atomic_dec(&request->data.phone->active_calls); |
|
250 | } else if (!list_empty(&box->calls)) { |
285 | } else if (!list_empty(&box->calls)) { |
251 | /* Handle requests */ |
286 | /* Handle requests */ |
252 | request = list_get_instance(box->calls.next, call_t, list); |
287 | request = list_get_instance(box->calls.next, call_t, list); |
253 | list_remove(&request->list); |
288 | list_remove(&request->list); |
254 | /* Append request to dispatch queue */ |
289 | /* Append request to dispatch queue */ |
255 | list_append(&request->list, &box->dispatched_calls); |
290 | list_append(&request->list, &box->dispatched_calls); |
256 | request->flags |= IPC_CALL_DISPATCHED; |
291 | request->flags |= IPC_CALL_DISPATCHED; |
257 | } else { |
292 | } else { |
258 | if (!(flags & IPC_WAIT_NONBLOCKING)) { |
293 | printf("WARNING: Spurious IPC wakeup.\n"); |
259 | /* Wait for event to appear */ |
- | |
260 | spinlock_unlock(&box->lock); |
294 | spinlock_unlock(&box->lock); |
261 | waitq_sleep(&box->wq); |
- | |
262 | spinlock_lock(&box->lock); |
- | |
263 | continue; |
- | |
264 | } |
- | |
265 | request = NULL; |
- | |
266 | } |
- | |
267 | break; |
295 | goto restart; |
268 | } |
296 | } |
269 | spinlock_unlock(&box->lock); |
297 | spinlock_unlock(&box->lock); |
270 | return request; |
298 | return request; |
271 | } |
299 | } |
272 | 300 |