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, |