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