Rev 2927 | Rev 3149 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2927 | Rev 3107 | ||
|---|---|---|---|
| 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 138... | Line 140... | ||
| 138 | * @param phone Initialized phone structure. |
140 | * @param phone Initialized phone structure. |
| 139 | * @param box Initialized answerbox structure. |
141 | * @param box Initialized answerbox structure. |
| 140 | */ |
142 | */ |
| 141 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
143 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
| 142 | { |
144 | { |
| 143 | spinlock_lock(&phone->lock); |
145 | mutex_lock(&phone->lock); |
| 144 | 146 | ||
| 145 | phone->state = IPC_PHONE_CONNECTED; |
147 | phone->state = IPC_PHONE_CONNECTED; |
| 146 | phone->callee = box; |
148 | phone->callee = box; |
| 147 | 149 | ||
| 148 | spinlock_lock(&box->lock); |
150 | spinlock_lock(&box->lock); |
| 149 | list_append(&phone->link, &box->connected_phones); |
151 | list_append(&phone->link, &box->connected_phones); |
| 150 | spinlock_unlock(&box->lock); |
152 | spinlock_unlock(&box->lock); |
| 151 | 153 | ||
| 152 | spinlock_unlock(&phone->lock); |
154 | mutex_unlock(&phone->lock); |
| 153 | } |
155 | } |
| 154 | 156 | ||
| 155 | /** Initialize a phone structure. |
157 | /** Initialize a phone structure. |
| 156 | * |
158 | * |
| 157 | * @param phone Phone structure to be initialized. |
159 | * @param phone Phone structure to be initialized. |
| 158 | */ |
160 | */ |
| 159 | void ipc_phone_init(phone_t *phone) |
161 | void ipc_phone_init(phone_t *phone) |
| 160 | { |
162 | { |
| 161 | spinlock_initialize(&phone->lock, "phone_lock"); |
163 | mutex_initialize(&phone->lock); |
| 162 | phone->callee = NULL; |
164 | phone->callee = NULL; |
| 163 | phone->state = IPC_PHONE_FREE; |
165 | phone->state = IPC_PHONE_FREE; |
| 164 | atomic_set(&phone->active_calls, 0); |
166 | atomic_set(&phone->active_calls, 0); |
| 165 | } |
167 | } |
| 166 | 168 | ||
| Line 259... | Line 261... | ||
| 259 | */ |
261 | */ |
| 260 | int ipc_call(phone_t *phone, call_t *call) |
262 | int ipc_call(phone_t *phone, call_t *call) |
| 261 | { |
263 | { |
| 262 | answerbox_t *box; |
264 | answerbox_t *box; |
| 263 | 265 | ||
| 264 | spinlock_lock(&phone->lock); |
266 | mutex_lock(&phone->lock); |
| 265 | if (phone->state != IPC_PHONE_CONNECTED) { |
267 | if (phone->state != IPC_PHONE_CONNECTED) { |
| 266 | spinlock_unlock(&phone->lock); |
268 | mutex_unlock(&phone->lock); |
| 267 | if (call->flags & IPC_CALL_FORWARDED) { |
269 | if (call->flags & IPC_CALL_FORWARDED) { |
| 268 | IPC_SET_RETVAL(call->data, EFORWARD); |
270 | IPC_SET_RETVAL(call->data, EFORWARD); |
| 269 | _ipc_answer_free_call(call); |
271 | _ipc_answer_free_call(call); |
| 270 | } else { |
272 | } else { |
| 271 | if (phone->state == IPC_PHONE_HUNGUP) |
273 | if (phone->state == IPC_PHONE_HUNGUP) |
| Line 276... | Line 278... | ||
| 276 | return ENOENT; |
278 | return ENOENT; |
| 277 | } |
279 | } |
| 278 | box = phone->callee; |
280 | box = phone->callee; |
| 279 | _ipc_call(phone, box, call); |
281 | _ipc_call(phone, box, call); |
| 280 | 282 | ||
| 281 | spinlock_unlock(&phone->lock); |
283 | mutex_unlock(&phone->lock); |
| 282 | return 0; |
284 | return 0; |
| 283 | } |
285 | } |
| 284 | 286 | ||
| 285 | /** Disconnect phone from answerbox. |
287 | /** Disconnect phone from answerbox. |
| 286 | * |
288 | * |
| Line 295... | Line 297... | ||
| 295 | int ipc_phone_hangup(phone_t *phone) |
297 | int ipc_phone_hangup(phone_t *phone) |
| 296 | { |
298 | { |
| 297 | answerbox_t *box; |
299 | answerbox_t *box; |
| 298 | call_t *call; |
300 | call_t *call; |
| 299 | 301 | ||
| 300 | spinlock_lock(&phone->lock); |
302 | mutex_lock(&phone->lock); |
| 301 | if (phone->state == IPC_PHONE_FREE || |
303 | if (phone->state == IPC_PHONE_FREE || |
| 302 | phone->state == IPC_PHONE_HUNGUP || |
304 | phone->state == IPC_PHONE_HUNGUP || |
| 303 | phone->state == IPC_PHONE_CONNECTING) { |
305 | phone->state == IPC_PHONE_CONNECTING) { |
| 304 | spinlock_unlock(&phone->lock); |
306 | mutex_unlock(&phone->lock); |
| 305 | return -1; |
307 | return -1; |
| 306 | } |
308 | } |
| 307 | box = phone->callee; |
309 | box = phone->callee; |
| 308 | if (phone->state != IPC_PHONE_SLAMMED) { |
310 | if (phone->state != IPC_PHONE_SLAMMED) { |
| 309 | /* Remove myself from answerbox */ |
311 | /* Remove myself from answerbox */ |
| Line 318... | Line 320... | ||
| 318 | _ipc_call(phone, box, call); |
320 | _ipc_call(phone, box, call); |
| 319 | } |
321 | } |
| 320 | } |
322 | } |
| 321 | 323 | ||
| 322 | phone->state = IPC_PHONE_HUNGUP; |
324 | phone->state = IPC_PHONE_HUNGUP; |
| 323 | spinlock_unlock(&phone->lock); |
325 | mutex_unlock(&phone->lock); |
| 324 | 326 | ||
| 325 | return 0; |
327 | return 0; |
| 326 | } |
328 | } |
| 327 | 329 | ||
| 328 | /** Forwards call from one answerbox to another one. |
330 | /** Forwards call from one answerbox to another one. |
| Line 447... | Line 449... | ||
| 447 | restart_phones: |
449 | restart_phones: |
| 448 | spinlock_lock(&TASK->answerbox.lock); |
450 | spinlock_lock(&TASK->answerbox.lock); |
| 449 | while (!list_empty(&TASK->answerbox.connected_phones)) { |
451 | while (!list_empty(&TASK->answerbox.connected_phones)) { |
| 450 | phone = list_get_instance(TASK->answerbox.connected_phones.next, |
452 | phone = list_get_instance(TASK->answerbox.connected_phones.next, |
| 451 | phone_t, link); |
453 | phone_t, link); |
| 452 | if (!spinlock_trylock(&phone->lock)) { |
454 | if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { |
| 453 | spinlock_unlock(&TASK->answerbox.lock); |
455 | spinlock_unlock(&TASK->answerbox.lock); |
| 454 | DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
456 | DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
| 455 | goto restart_phones; |
457 | goto restart_phones; |
| 456 | } |
458 | } |
| 457 | 459 | ||
| 458 | /* Disconnect phone */ |
460 | /* Disconnect phone */ |
| 459 | ASSERT(phone->state == IPC_PHONE_CONNECTED); |
461 | ASSERT(phone->state == IPC_PHONE_CONNECTED); |
| 460 | phone->state = IPC_PHONE_SLAMMED; |
462 | phone->state = IPC_PHONE_SLAMMED; |
| 461 | list_remove(&phone->link); |
463 | list_remove(&phone->link); |
| 462 | 464 | ||
| 463 | spinlock_unlock(&phone->lock); |
465 | mutex_unlock(&phone->lock); |
| 464 | } |
466 | } |
| 465 | 467 | ||
| 466 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
468 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
| 467 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
469 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
| 468 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
470 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
| Line 533... | Line 535... | ||
| 533 | return; |
535 | return; |
| 534 | 536 | ||
| 535 | /* Print opened phones & details */ |
537 | /* Print opened phones & details */ |
| 536 | printf("PHONE:\n"); |
538 | printf("PHONE:\n"); |
| 537 | for (i = 0; i < IPC_MAX_PHONES; i++) { |
539 | for (i = 0; i < IPC_MAX_PHONES; i++) { |
| 538 | spinlock_lock(&task->phones[i].lock); |
540 | if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { |
| - | 541 | printf("%d: mutex busy\n", i); |
|
| - | 542 | continue; |
|
| - | 543 | } |
|
| 539 | if (task->phones[i].state != IPC_PHONE_FREE) { |
544 | if (task->phones[i].state != IPC_PHONE_FREE) { |
| 540 | printf("%d: ", i); |
545 | printf("%d: ", i); |
| 541 | switch (task->phones[i].state) { |
546 | switch (task->phones[i].state) { |
| 542 | case IPC_PHONE_CONNECTING: |
547 | case IPC_PHONE_CONNECTING: |
| 543 | printf("connecting "); |
548 | printf("connecting "); |
| Line 558... | Line 563... | ||
| 558 | break; |
563 | break; |
| 559 | } |
564 | } |
| 560 | printf("active: %d\n", |
565 | printf("active: %d\n", |
| 561 | atomic_get(&task->phones[i].active_calls)); |
566 | atomic_get(&task->phones[i].active_calls)); |
| 562 | } |
567 | } |
| 563 | spinlock_unlock(&task->phones[i].lock); |
568 | mutex_unlock(&task->phones[i].lock); |
| 564 | } |
569 | } |
| 565 | 570 | ||
| 566 | 571 | ||
| 567 | /* Print answerbox - calls */ |
572 | /* Print answerbox - calls */ |
| 568 | spinlock_lock(&task->answerbox.lock); |
573 | spinlock_lock(&task->answerbox.lock); |
| Line 577... | Line 582... | ||
| 577 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
582 | IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
| 578 | call->flags); |
583 | call->flags); |
| 579 | } |
584 | } |
| 580 | /* Print answerbox - calls */ |
585 | /* Print answerbox - calls */ |
| 581 | printf("ABOX - DISPATCHED CALLS:\n"); |
586 | printf("ABOX - DISPATCHED CALLS:\n"); |
| 582 | for (tmp=task->answerbox.dispatched_calls.next; |
587 | for (tmp = task->answerbox.dispatched_calls.next; |
| 583 | tmp != &task->answerbox.dispatched_calls; |
588 | tmp != &task->answerbox.dispatched_calls; |
| 584 | tmp = tmp->next) { |
589 | tmp = tmp->next) { |
| 585 | call = list_get_instance(tmp, call_t, link); |
590 | call = list_get_instance(tmp, call_t, link); |
| 586 | printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
591 | printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
| 587 | "A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |
592 | "A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |