Subversion Repositories HelenOS

Rev

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,