Rev 1086 | Rev 1090 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1086 | Rev 1088 | ||
---|---|---|---|
Line 102... | Line 102... | ||
102 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
102 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
103 | { |
103 | { |
104 | spinlock_lock(&phone->lock); |
104 | spinlock_lock(&phone->lock); |
105 | 105 | ||
106 | ASSERT(!phone->callee); |
106 | ASSERT(!phone->callee); |
107 | phone->busy = 1; |
107 | phone->busy = IPC_BUSY_CONNECTED; |
108 | phone->callee = box; |
108 | phone->callee = box; |
109 | 109 | ||
110 | spinlock_lock(&box->lock); |
110 | spinlock_lock(&box->lock); |
111 | list_append(&phone->list, &box->connected_phones); |
111 | list_append(&phone->list, &box->connected_phones); |
112 | spinlock_unlock(&box->lock); |
112 | spinlock_unlock(&box->lock); |
Line 118... | Line 118... | ||
118 | */ |
118 | */ |
119 | void ipc_phone_init(phone_t *phone) |
119 | void ipc_phone_init(phone_t *phone) |
120 | { |
120 | { |
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 = IPC_BUSY_FREE; |
- | 124 | atomic_set(&phone->active_calls, 0); |
|
124 | } |
125 | } |
125 | 126 | ||
126 | /** Helper function to facilitate synchronous calls */ |
127 | /** Helper function to facilitate synchronous calls */ |
127 | void ipc_call_sync(phone_t *phone, call_t *request) |
128 | void ipc_call_sync(phone_t *phone, call_t *request) |
128 | { |
129 | { |
Line 169... | Line 170... | ||
169 | } |
170 | } |
170 | 171 | ||
171 | /* Unsafe unchecking ipc_call */ |
172 | /* Unsafe unchecking ipc_call */ |
172 | static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) |
173 | static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) |
173 | { |
174 | { |
- | 175 | if (! (call->flags & IPC_CALL_FORWARDED)) { |
|
174 | atomic_inc(&phone->active_calls); |
176 | atomic_inc(&phone->active_calls); |
175 | call->data.phone = phone; |
177 | call->data.phone = phone; |
- | 178 | } |
|
176 | 179 | ||
177 | spinlock_lock(&box->lock); |
180 | spinlock_lock(&box->lock); |
178 | list_append(&call->list, &box->calls); |
181 | list_append(&call->list, &box->calls); |
179 | spinlock_unlock(&box->lock); |
182 | spinlock_unlock(&box->lock); |
180 | waitq_wakeup(&box->wq, 0); |
183 | waitq_wakeup(&box->wq, 0); |
Line 183... | Line 186... | ||
183 | /** Send a asynchronous request using phone to answerbox |
186 | /** Send a asynchronous request using phone to answerbox |
184 | * |
187 | * |
185 | * @param phone Phone connected to answerbox |
188 | * @param phone Phone connected to answerbox |
186 | * @param request Request to be sent |
189 | * @param request Request to be sent |
187 | */ |
190 | */ |
188 | void ipc_call(phone_t *phone, call_t *call) |
191 | int ipc_call(phone_t *phone, call_t *call) |
189 | { |
192 | { |
190 | answerbox_t *box; |
193 | answerbox_t *box; |
191 | 194 | ||
192 | spinlock_lock(&phone->lock); |
195 | spinlock_lock(&phone->lock); |
193 | 196 | ||
194 | box = phone->callee; |
197 | box = phone->callee; |
195 | if (!box) { |
198 | if (!box) { |
196 | /* Trying to send over disconnected phone */ |
199 | /* Trying to send over disconnected phone */ |
197 | spinlock_unlock(&phone->lock); |
200 | spinlock_unlock(&phone->lock); |
- | 201 | if (call->flags & IPC_CALL_FORWARDED) { |
|
- | 202 | IPC_SET_RETVAL(call->data, EFORWARD); |
|
- | 203 | } else { /* Simulate sending a message */ |
|
- | 204 | call->data.phone = phone; |
|
- | 205 | atomic_inc(&phone->active_calls); |
|
- | 206 | if (phone->busy == IPC_BUSY_CONNECTED) |
|
- | 207 | IPC_SET_RETVAL(call->data, EHANGUP); |
|
- | 208 | else |
|
- | 209 | IPC_SET_RETVAL(call->data, ENOENT); |
|
- | 210 | } |
|
198 | 211 | ||
199 | call->data.phone = phone; |
- | |
200 | IPC_SET_RETVAL(call->data, ENOENT); |
- | |
201 | _ipc_answer_free_call(call); |
212 | _ipc_answer_free_call(call); |
202 | return; |
213 | return ENOENT; |
203 | } |
214 | } |
204 | _ipc_call(phone, box, call); |
215 | _ipc_call(phone, box, call); |
205 | 216 | ||
206 | spinlock_unlock(&phone->lock); |
217 | spinlock_unlock(&phone->lock); |
- | 218 | return 0; |
|
207 | } |
219 | } |
208 | 220 | ||
209 | /** Disconnect phone from answerbox |
221 | /** Disconnect phone from answerbox |
210 | * |
222 | * |
211 | * It is allowed to call disconnect on already disconnected phone |
223 | * It is allowed to call disconnect on already disconnected phone |
Line 218... | Line 230... | ||
218 | call_t *call; |
230 | call_t *call; |
219 | 231 | ||
220 | spinlock_lock(&phone->lock); |
232 | spinlock_lock(&phone->lock); |
221 | box = phone->callee; |
233 | box = phone->callee; |
222 | if (!box) { |
234 | if (!box) { |
- | 235 | if (phone->busy == IPC_BUSY_CONNECTING) { |
|
- | 236 | spinlock_unlock(&phone->lock); |
|
- | 237 | return -1; |
|
- | 238 | } |
|
- | 239 | /* Already disconnected phone */ |
|
- | 240 | phone->busy = IPC_BUSY_FREE; |
|
223 | spinlock_unlock(&phone->lock); |
241 | spinlock_unlock(&phone->lock); |
224 | return -1; |
242 | return 0; |
225 | } |
243 | } |
226 | 244 | ||
227 | spinlock_lock(&box->lock); |
245 | spinlock_lock(&box->lock); |
228 | list_remove(&phone->list); |
246 | list_remove(&phone->list); |
229 | phone->callee = NULL; |
247 | phone->callee = NULL; |
Line 232... | Line 250... | ||
232 | call = ipc_call_alloc(); |
250 | call = ipc_call_alloc(); |
233 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
251 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
234 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
252 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
235 | _ipc_call(phone, box, call); |
253 | _ipc_call(phone, box, call); |
236 | 254 | ||
237 | phone->busy = 0; |
255 | phone->busy = IPC_BUSY_FREE; |
238 | 256 | ||
239 | spinlock_unlock(&phone->lock); |
257 | spinlock_unlock(&phone->lock); |
240 | 258 | ||
241 | return 0; |
259 | return 0; |
242 | } |
260 | } |
Line 244... | Line 262... | ||
244 | /** Forwards call from one answerbox to a new one |
262 | /** Forwards call from one answerbox to a new one |
245 | * |
263 | * |
246 | * @param request Request to be forwarded |
264 | * @param request Request to be forwarded |
247 | * @param newbox Target answerbox |
265 | * @param newbox Target answerbox |
248 | * @param oldbox Old answerbox |
266 | * @param oldbox Old answerbox |
- | 267 | * @return 0 on forward ok, error code, if there was error |
|
- | 268 | * |
|
- | 269 | * - the return value serves only as an information for the forwarder, |
|
- | 270 | * the original caller is notified automatically with EFORWARD |
|
249 | */ |
271 | */ |
250 | void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
272 | int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
251 | { |
273 | { |
252 | spinlock_lock(&oldbox->lock); |
274 | spinlock_lock(&oldbox->lock); |
253 | atomic_dec(&call->data.phone->active_calls); |
- | |
254 | list_remove(&call->list); |
275 | list_remove(&call->list); |
255 | spinlock_unlock(&oldbox->lock); |
276 | spinlock_unlock(&oldbox->lock); |
256 | 277 | ||
257 | ipc_call(newphone, call); |
278 | return ipc_call(newphone, call); |
258 | } |
279 | } |
259 | 280 | ||
260 | 281 | ||
261 | /** Wait for phone call |
282 | /** Wait for phone call |
262 | * |
283 | * |
Line 277... | Line 298... | ||
277 | spinlock_lock(&box->lock); |
298 | spinlock_lock(&box->lock); |
278 | if (!list_empty(&box->answers)) { |
299 | if (!list_empty(&box->answers)) { |
279 | /* Handle asynchronous answers */ |
300 | /* Handle asynchronous answers */ |
280 | request = list_get_instance(box->answers.next, call_t, list); |
301 | request = list_get_instance(box->answers.next, call_t, list); |
281 | list_remove(&request->list); |
302 | 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); |
303 | atomic_dec(&request->data.phone->active_calls); |
285 | } else if (!list_empty(&box->calls)) { |
304 | } else if (!list_empty(&box->calls)) { |
286 | /* Handle requests */ |
305 | /* Handle requests */ |
287 | request = list_get_instance(box->calls.next, call_t, list); |
306 | request = list_get_instance(box->calls.next, call_t, list); |
288 | list_remove(&request->list); |
307 | list_remove(&request->list); |
Line 311... | Line 330... | ||
311 | * |
330 | * |
312 | * |
331 | * |
313 | */ |
332 | */ |
314 | void ipc_cleanup(task_t *task) |
333 | void ipc_cleanup(task_t *task) |
315 | { |
334 | { |
- | 335 | int i; |
|
- | 336 | ||
- | 337 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
|
- | 338 | for (i=0;i < IPC_MAX_PHONES; i++) |
|
- | 339 | ipc_phone_hangup(&task->phones[i]); |
|
- | 340 | ||
- | 341 | /* Disconnect all phones connected to answerbox */ |
|
- | 342 | ||
316 | /* Cancel all calls in my dispatch queue */ |
343 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
317 | 344 | ||
- | 345 | /* Wait for all async answers to arrive */ |
|
318 | } |
346 | } |