Subversion Repositories HelenOS

Rev

Rev 2802 | Rev 3054 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2802 Rev 3020
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,