Rev 3037 | Rev 3424 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3037 | Rev 3042 | ||
---|---|---|---|
Line 35... | Line 35... | ||
35 | /* Lock ordering |
35 | /* Lock ordering |
36 | * |
36 | * |
37 | * First the answerbox, then the phone. |
37 | * First the answerbox, then the phone. |
38 | */ |
38 | */ |
39 | 39 | ||
- | 40 | #include <synch/synch.h> |
|
40 | #include <synch/spinlock.h> |
41 | #include <synch/spinlock.h> |
- | 42 | #include <synch/mutex.h> |
|
41 | #include <synch/waitq.h> |
43 | #include <synch/waitq.h> |
42 | #include <synch/synch.h> |
44 | #include <synch/synch.h> |
43 | #include <ipc/ipc.h> |
45 | #include <ipc/ipc.h> |
44 | #include <errno.h> |
46 | #include <errno.h> |
45 | #include <mm/slab.h> |
47 | #include <mm/slab.h> |
Line 139... | Line 141... | ||
139 | * @param phone Initialized phone structure. |
141 | * @param phone Initialized phone structure. |
140 | * @param box Initialized answerbox structure. |
142 | * @param box Initialized answerbox structure. |
141 | */ |
143 | */ |
142 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
144 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
143 | { |
145 | { |
144 | spinlock_lock(&phone->lock); |
146 | mutex_lock(&phone->lock); |
145 | 147 | ||
146 | phone->state = IPC_PHONE_CONNECTED; |
148 | phone->state = IPC_PHONE_CONNECTED; |
147 | phone->callee = box; |
149 | phone->callee = box; |
148 | 150 | ||
149 | spinlock_lock(&box->lock); |
151 | spinlock_lock(&box->lock); |
150 | list_append(&phone->link, &box->connected_phones); |
152 | list_append(&phone->link, &box->connected_phones); |
151 | spinlock_unlock(&box->lock); |
153 | spinlock_unlock(&box->lock); |
152 | 154 | ||
153 | spinlock_unlock(&phone->lock); |
155 | mutex_unlock(&phone->lock); |
154 | } |
156 | } |
155 | 157 | ||
156 | /** Initialize a phone structure. |
158 | /** Initialize a phone structure. |
157 | * |
159 | * |
158 | * @param phone Phone structure to be initialized. |
160 | * @param phone Phone structure to be initialized. |
159 | */ |
161 | */ |
160 | void ipc_phone_init(phone_t *phone) |
162 | void ipc_phone_init(phone_t *phone) |
161 | { |
163 | { |
162 | spinlock_initialize(&phone->lock, "phone_lock"); |
164 | mutex_initialize(&phone->lock); |
163 | phone->callee = NULL; |
165 | phone->callee = NULL; |
164 | phone->state = IPC_PHONE_FREE; |
166 | phone->state = IPC_PHONE_FREE; |
165 | atomic_set(&phone->active_calls, 0); |
167 | atomic_set(&phone->active_calls, 0); |
166 | } |
168 | } |
167 | 169 | ||
Line 260... | Line 262... | ||
260 | */ |
262 | */ |
261 | int ipc_call(phone_t *phone, call_t *call) |
263 | int ipc_call(phone_t *phone, call_t *call) |
262 | { |
264 | { |
263 | answerbox_t *box; |
265 | answerbox_t *box; |
264 | 266 | ||
265 | spinlock_lock(&phone->lock); |
267 | mutex_lock(&phone->lock); |
266 | if (phone->state != IPC_PHONE_CONNECTED) { |
268 | if (phone->state != IPC_PHONE_CONNECTED) { |
267 | spinlock_unlock(&phone->lock); |
269 | mutex_unlock(&phone->lock); |
268 | if (call->flags & IPC_CALL_FORWARDED) { |
270 | if (call->flags & IPC_CALL_FORWARDED) { |
269 | IPC_SET_RETVAL(call->data, EFORWARD); |
271 | IPC_SET_RETVAL(call->data, EFORWARD); |
270 | _ipc_answer_free_call(call); |
272 | _ipc_answer_free_call(call); |
271 | } else { |
273 | } else { |
272 | if (phone->state == IPC_PHONE_HUNGUP) |
274 | if (phone->state == IPC_PHONE_HUNGUP) |
Line 277... | Line 279... | ||
277 | return ENOENT; |
279 | return ENOENT; |
278 | } |
280 | } |
279 | box = phone->callee; |
281 | box = phone->callee; |
280 | _ipc_call(phone, box, call); |
282 | _ipc_call(phone, box, call); |
281 | 283 | ||
282 | spinlock_unlock(&phone->lock); |
284 | mutex_unlock(&phone->lock); |
283 | return 0; |
285 | return 0; |
284 | } |
286 | } |
285 | 287 | ||
286 | /** Disconnect phone from answerbox. |
288 | /** Disconnect phone from answerbox. |
287 | * |
289 | * |
Line 296... | Line 298... | ||
296 | int ipc_phone_hangup(phone_t *phone) |
298 | int ipc_phone_hangup(phone_t *phone) |
297 | { |
299 | { |
298 | answerbox_t *box; |
300 | answerbox_t *box; |
299 | call_t *call; |
301 | call_t *call; |
300 | 302 | ||
301 | spinlock_lock(&phone->lock); |
303 | mutex_lock(&phone->lock); |
302 | if (phone->state == IPC_PHONE_FREE || |
304 | if (phone->state == IPC_PHONE_FREE || |
303 | phone->state == IPC_PHONE_HUNGUP || |
305 | phone->state == IPC_PHONE_HUNGUP || |
304 | phone->state == IPC_PHONE_CONNECTING) { |
306 | phone->state == IPC_PHONE_CONNECTING) { |
305 | spinlock_unlock(&phone->lock); |
307 | mutex_unlock(&phone->lock); |
306 | return -1; |
308 | return -1; |
307 | } |
309 | } |
308 | box = phone->callee; |
310 | box = phone->callee; |
309 | if (phone->state != IPC_PHONE_SLAMMED) { |
311 | if (phone->state != IPC_PHONE_SLAMMED) { |
310 | /* Remove myself from answerbox */ |
312 | /* Remove myself from answerbox */ |
Line 319... | Line 321... | ||
319 | _ipc_call(phone, box, call); |
321 | _ipc_call(phone, box, call); |
320 | } |
322 | } |
321 | } |
323 | } |
322 | 324 | ||
323 | phone->state = IPC_PHONE_HUNGUP; |
325 | phone->state = IPC_PHONE_HUNGUP; |
324 | spinlock_unlock(&phone->lock); |
326 | mutex_unlock(&phone->lock); |
325 | 327 | ||
326 | return 0; |
328 | return 0; |
327 | } |
329 | } |
328 | 330 | ||
329 | /** Forwards call from one answerbox to another one. |
331 | /** Forwards call from one answerbox to another one. |
Line 445... | Line 447... | ||
445 | ipl = interrupts_disable(); |
447 | ipl = interrupts_disable(); |
446 | spinlock_lock(&box->lock); |
448 | spinlock_lock(&box->lock); |
447 | while (!list_empty(&box->connected_phones)) { |
449 | while (!list_empty(&box->connected_phones)) { |
448 | phone = list_get_instance(box->connected_phones.next, |
450 | phone = list_get_instance(box->connected_phones.next, |
449 | phone_t, link); |
451 | phone_t, link); |
450 | if (!spinlock_trylock(&phone->lock)) { |
452 | if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { |
451 | spinlock_unlock(&box->lock); |
453 | spinlock_unlock(&box->lock); |
452 | interrupts_restore(ipl); |
454 | interrupts_restore(ipl); |
453 | DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
455 | DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
454 | goto restart_phones; |
456 | goto restart_phones; |
455 | } |
457 | } |
Line 459... | Line 461... | ||
459 | 461 | ||
460 | list_remove(&phone->link); |
462 | list_remove(&phone->link); |
461 | phone->state = IPC_PHONE_SLAMMED; |
463 | phone->state = IPC_PHONE_SLAMMED; |
462 | 464 | ||
463 | if (notify_box) { |
465 | if (notify_box) { |
464 | spinlock_unlock(&phone->lock); |
466 | mutex_unlock(&phone->lock); |
465 | spinlock_unlock(&box->lock); |
467 | spinlock_unlock(&box->lock); |
466 | interrupts_restore(ipl); |
468 | interrupts_restore(ipl); |
467 | 469 | ||
468 | /* |
470 | /* |
469 | * Send one message to the answerbox for each |
471 | * Send one message to the answerbox for each |
Line 480... | Line 482... | ||
480 | 482 | ||
481 | /* Must start again */ |
483 | /* Must start again */ |
482 | goto restart_phones; |
484 | goto restart_phones; |
483 | } |
485 | } |
484 | 486 | ||
485 | spinlock_unlock(&phone->lock); |
487 | mutex_unlock(&phone->lock); |
486 | } |
488 | } |
487 | 489 | ||
488 | spinlock_unlock(&box->lock); |
490 | spinlock_unlock(&box->lock); |
489 | interrupts_restore(ipl); |
491 | interrupts_restore(ipl); |
490 | 492 | ||
Line 623... | Line 625... | ||
623 | return; |
625 | return; |
624 | 626 | ||
625 | /* Print opened phones & details */ |
627 | /* Print opened phones & details */ |
626 | printf("PHONE:\n"); |
628 | printf("PHONE:\n"); |
627 | for (i = 0; i < IPC_MAX_PHONES; i++) { |
629 | for (i = 0; i < IPC_MAX_PHONES; i++) { |
628 | spinlock_lock(&task->phones[i].lock); |
630 | if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { |
- | 631 | printf("%d: mutex busy\n", i); |
|
- | 632 | continue; |
|
- | 633 | } |
|
629 | if (task->phones[i].state != IPC_PHONE_FREE) { |
634 | if (task->phones[i].state != IPC_PHONE_FREE) { |
630 | printf("%d: ", i); |
635 | printf("%d: ", i); |
631 | switch (task->phones[i].state) { |
636 | switch (task->phones[i].state) { |
632 | case IPC_PHONE_CONNECTING: |
637 | case IPC_PHONE_CONNECTING: |
633 | printf("connecting "); |
638 | printf("connecting "); |
Line 648... | Line 653... | ||
648 | break; |
653 | break; |
649 | } |
654 | } |
650 | printf("active: %d\n", |
655 | printf("active: %d\n", |
651 | atomic_get(&task->phones[i].active_calls)); |
656 | atomic_get(&task->phones[i].active_calls)); |
652 | } |
657 | } |
653 | spinlock_unlock(&task->phones[i].lock); |
658 | mutex_unlock(&task->phones[i].lock); |
654 | } |
659 | } |
655 | 660 | ||
656 | 661 | ||
657 | /* Print answerbox - calls */ |
662 | /* Print answerbox - calls */ |
658 | spinlock_lock(&task->answerbox.lock); |
663 | spinlock_lock(&task->answerbox.lock); |
Line 667... | Line 672... | ||
667 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
672 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
668 | call->flags); |
673 | call->flags); |
669 | } |
674 | } |
670 | /* Print answerbox - calls */ |
675 | /* Print answerbox - calls */ |
671 | printf("ABOX - DISPATCHED CALLS:\n"); |
676 | printf("ABOX - DISPATCHED CALLS:\n"); |
672 | for (tmp=task->answerbox.dispatched_calls.next; |
677 | for (tmp = task->answerbox.dispatched_calls.next; |
673 | tmp != &task->answerbox.dispatched_calls; |
678 | tmp != &task->answerbox.dispatched_calls; |
674 | tmp = tmp->next) { |
679 | tmp = tmp->next) { |
675 | call = list_get_instance(tmp, call_t, link); |
680 | call = list_get_instance(tmp, call_t, link); |
676 | printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
681 | printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
677 | "A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |
682 | "A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |