Subversion Repositories HelenOS

Rev

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

Rev 1568 Rev 1573
Line 108... Line 108...
108
/** Connect phone to answerbox */
108
/** Connect phone to answerbox */
109
void ipc_phone_connect(phone_t *phone, answerbox_t *box)
109
void ipc_phone_connect(phone_t *phone, answerbox_t *box)
110
{
110
{
111
    spinlock_lock(&phone->lock);
111
    spinlock_lock(&phone->lock);
112
 
112
 
113
    ASSERT(!phone->callee);
-
 
114
    phone->state = IPC_PHONE_CONNECTED;
113
    phone->state = IPC_PHONE_CONNECTED;
115
    phone->callee = box;
114
    phone->callee = box;
116
 
115
 
117
    spinlock_lock(&box->lock);
116
    spinlock_lock(&box->lock);
118
    list_append(&phone->list, &box->connected_phones);
117
    list_append(&phone->link, &box->connected_phones);
119
    spinlock_unlock(&box->lock);
118
    spinlock_unlock(&box->lock);
120
 
119
 
121
    spinlock_unlock(&phone->lock);
120
    spinlock_unlock(&phone->lock);
122
}
121
}
123
 
122
 
Line 153... Line 152...
153
    answerbox_t *callerbox = call->callerbox;
152
    answerbox_t *callerbox = call->callerbox;
154
 
153
 
155
    call->flags |= IPC_CALL_ANSWERED;
154
    call->flags |= IPC_CALL_ANSWERED;
156
 
155
 
157
    spinlock_lock(&callerbox->lock);
156
    spinlock_lock(&callerbox->lock);
158
    list_append(&call->list, &callerbox->answers);
157
    list_append(&call->link, &callerbox->answers);
159
    spinlock_unlock(&callerbox->lock);
158
    spinlock_unlock(&callerbox->lock);
160
    waitq_wakeup(&callerbox->wq, 0);
159
    waitq_wakeup(&callerbox->wq, 0);
161
}
160
}
162
 
161
 
163
/** Answer message, that is in callee queue
162
/** Answer message, that is in callee queue
Line 167... Line 166...
167
 */
166
 */
168
void ipc_answer(answerbox_t *box, call_t *call)
167
void ipc_answer(answerbox_t *box, call_t *call)
169
{
168
{
170
    /* Remove from active box */
169
    /* Remove from active box */
171
    spinlock_lock(&box->lock);
170
    spinlock_lock(&box->lock);
172
    list_remove(&call->list);
171
    list_remove(&call->link);
173
    spinlock_unlock(&box->lock);
172
    spinlock_unlock(&box->lock);
174
    /* Send back answer */
173
    /* Send back answer */
175
    _ipc_answer_free_call(call);
174
    _ipc_answer_free_call(call);
176
}
175
}
177
 
176
 
Line 195... Line 194...
195
        atomic_inc(&phone->active_calls);
194
        atomic_inc(&phone->active_calls);
196
        call->data.phone = phone;
195
        call->data.phone = phone;
197
    }
196
    }
198
 
197
 
199
    spinlock_lock(&box->lock);
198
    spinlock_lock(&box->lock);
200
    list_append(&call->list, &box->calls);
199
    list_append(&call->link, &box->calls);
201
    spinlock_unlock(&box->lock);
200
    spinlock_unlock(&box->lock);
202
    waitq_wakeup(&box->wq, 0);
201
    waitq_wakeup(&box->wq, 0);
203
}
202
}
204
 
203
 
205
/** Send a asynchronous request using phone to answerbox
204
/** Send a asynchronous request using phone to answerbox
Line 259... Line 258...
259
    }
258
    }
260
    box = phone->callee;
259
    box = phone->callee;
261
    if (phone->state != IPC_PHONE_SLAMMED) {
260
    if (phone->state != IPC_PHONE_SLAMMED) {
262
        /* Remove myself from answerbox */
261
        /* Remove myself from answerbox */
263
        spinlock_lock(&box->lock);
262
        spinlock_lock(&box->lock);
264
        list_remove(&phone->list);
263
        list_remove(&phone->link);
265
        spinlock_unlock(&box->lock);
264
        spinlock_unlock(&box->lock);
266
 
265
 
267
        if (phone->state != IPC_PHONE_SLAMMED) {
266
        if (phone->state != IPC_PHONE_SLAMMED) {
268
            call = ipc_call_alloc(0);
267
            call = ipc_call_alloc(0);
269
            IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
268
            IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
Line 274... Line 273...
274
 
273
 
275
    if (aggressive && atomic_get(&phone->active_calls) > 0) {
274
    if (aggressive && atomic_get(&phone->active_calls) > 0) {
276
        /* TODO: Do some stuff be VERY aggressive */
275
        /* TODO: Do some stuff be VERY aggressive */
277
    }
276
    }
278
 
277
 
279
    phone->callee = 0;
-
 
280
   
-
 
281
    phone->state = IPC_PHONE_HUNGUP;
278
    phone->state = IPC_PHONE_HUNGUP;
282
    spinlock_unlock(&phone->lock);
279
    spinlock_unlock(&phone->lock);
283
 
280
 
284
    return 0;
281
    return 0;
285
}
282
}
Line 295... Line 292...
295
 *   the original caller is notified automatically with EFORWARD
292
 *   the original caller is notified automatically with EFORWARD
296
 */
293
 */
297
int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
294
int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
298
{
295
{
299
    spinlock_lock(&oldbox->lock);
296
    spinlock_lock(&oldbox->lock);
300
    list_remove(&call->list);
297
    list_remove(&call->link);
301
    spinlock_unlock(&oldbox->lock);
298
    spinlock_unlock(&oldbox->lock);
302
 
299
 
303
    return ipc_call(newphone, call);
300
    return ipc_call(newphone, call);
304
}
301
}
305
 
302
 
Line 328... Line 325...
328
    spinlock_lock(&box->lock);
325
    spinlock_lock(&box->lock);
329
    if (!list_empty(&box->irq_notifs)) {
326
    if (!list_empty(&box->irq_notifs)) {
330
        ipl = interrupts_disable();
327
        ipl = interrupts_disable();
331
        spinlock_lock(&box->irq_lock);
328
        spinlock_lock(&box->irq_lock);
332
 
329
 
333
        request = list_get_instance(box->irq_notifs.next, call_t, list);
330
        request = list_get_instance(box->irq_notifs.next, call_t, link);
334
        list_remove(&request->list);
331
        list_remove(&request->link);
335
 
332
 
336
        spinlock_unlock(&box->irq_lock);
333
        spinlock_unlock(&box->irq_lock);
337
        interrupts_restore(ipl);
334
        interrupts_restore(ipl);
338
    } else if (!list_empty(&box->answers)) {
335
    } else if (!list_empty(&box->answers)) {
339
        /* Handle asynchronous answers */
336
        /* Handle asynchronous answers */
340
        request = list_get_instance(box->answers.next, call_t, list);
337
        request = list_get_instance(box->answers.next, call_t, link);
341
        list_remove(&request->list);
338
        list_remove(&request->link);
342
        atomic_dec(&request->data.phone->active_calls);
339
        atomic_dec(&request->data.phone->active_calls);
343
    } else if (!list_empty(&box->calls)) {
340
    } else if (!list_empty(&box->calls)) {
344
        /* Handle requests */
341
        /* Handle requests */
345
        request = list_get_instance(box->calls.next, call_t, list);
342
        request = list_get_instance(box->calls.next, call_t, link);
346
        list_remove(&request->list);
343
        list_remove(&request->link);
347
        /* Append request to dispatch queue */
344
        /* Append request to dispatch queue */
348
        list_append(&request->list, &box->dispatched_calls);
345
        list_append(&request->link, &box->dispatched_calls);
349
    } else {
346
    } else {
350
        /* This can happen regularly after ipc_cleanup, remove
347
        /* This can happen regularly after ipc_cleanup, remove
351
         * the warning in the future when the IPC is
348
         * the warning in the future when the IPC is
352
         * more debugged */
349
         * more debugged */
353
        printf("WARNING: Spurious IPC wakeup.\n");
350
        printf("WARNING: Spurious IPC wakeup.\n");
Line 362... Line 359...
362
static void ipc_cleanup_call_list(link_t *lst)
359
static void ipc_cleanup_call_list(link_t *lst)
363
{
360
{
364
    call_t *call;
361
    call_t *call;
365
 
362
 
366
    while (!list_empty(lst)) {
363
    while (!list_empty(lst)) {
367
        call = list_get_instance(lst->next, call_t, list);
364
        call = list_get_instance(lst->next, call_t, link);
368
        list_remove(&call->list);
365
        list_remove(&call->link);
369
 
366
 
370
        IPC_SET_RETVAL(call->data, EHANGUP);
367
        IPC_SET_RETVAL(call->data, EHANGUP);
371
        _ipc_answer_free_call(call);
368
        _ipc_answer_free_call(call);
372
    }
369
    }
373
}
370
}
Line 392... Line 389...
392
    /* Disconnect all phones connected to our answerbox */
389
    /* Disconnect all phones connected to our answerbox */
393
restart_phones:
390
restart_phones:
394
    spinlock_lock(&task->answerbox.lock);
391
    spinlock_lock(&task->answerbox.lock);
395
    while (!list_empty(&task->answerbox.connected_phones)) {
392
    while (!list_empty(&task->answerbox.connected_phones)) {
396
        phone = list_get_instance(task->answerbox.connected_phones.next,
393
        phone = list_get_instance(task->answerbox.connected_phones.next,
397
                      phone_t,
394
                      phone_t, link);
398
                      list);
-
 
399
        if (! spinlock_trylock(&phone->lock)) {
395
        if (! spinlock_trylock(&phone->lock)) {
400
            spinlock_unlock(&task->answerbox.lock);
396
            spinlock_unlock(&task->answerbox.lock);
401
            goto restart_phones;
397
            goto restart_phones;
402
        }
398
        }
403
       
399
       
404
        /* Disconnect phone */
400
        /* Disconnect phone */
405
        ASSERT(phone->state == IPC_PHONE_CONNECTED);
401
        ASSERT(phone->state == IPC_PHONE_CONNECTED);
406
        phone->state = IPC_PHONE_SLAMMED;
402
        phone->state = IPC_PHONE_SLAMMED;
407
        list_remove(&phone->list);
403
        list_remove(&phone->link);
408
 
404
 
409
        spinlock_unlock(&phone->lock);
405
        spinlock_unlock(&phone->lock);
410
    }
406
    }
411
 
407
 
412
    /* Answer all messages in 'calls' and 'dispatched_calls' queues */
408
    /* Answer all messages in 'calls' and 'dispatched_calls' queues */
Line 449... Line 445...
449
                      0,
445
                      0,
450
                      NULL, NULL, 0);
446
                      NULL, NULL, 0);
451
    ipc_irq_make_table(IRQ_COUNT);
447
    ipc_irq_make_table(IRQ_COUNT);
452
}
448
}
453
 
449
 
-
 
450
 
-
 
451
/** Kconsole - list answerbox contents */
-
 
452
void ipc_print_task(task_id_t taskid)
-
 
453
{
-
 
454
    task_t *task;
-
 
455
    int i;
-
 
456
    call_t *call;
-
 
457
    link_t *tmp;
-
 
458
   
-
 
459
    spinlock_lock(&tasks_lock);
-
 
460
    task = task_find_by_id(taskid);
-
 
461
    if (task)
-
 
462
        spinlock_lock(&task->lock);
-
 
463
    spinlock_unlock(&tasks_lock);
-
 
464
    if (!task)
-
 
465
        return;
-
 
466
 
-
 
467
    /* Print opened phones & details */
-
 
468
    printf("PHONE:\n");
-
 
469
    for (i=0; i < IPC_MAX_PHONES;i++) {
-
 
470
        spinlock_lock(&task->phones[i].lock);
-
 
471
        if (task->phones[i].state != IPC_PHONE_FREE) {
-
 
472
            printf("%d: ",i);
-
 
473
            switch (task->phones[i].state) {
-
 
474
            case IPC_PHONE_CONNECTING:
-
 
475
                printf("connecting ");
-
 
476
                break;
-
 
477
            case IPC_PHONE_CONNECTED:
-
 
478
                printf("connected to: %P ",
-
 
479
                       task->phones[i].callee);
-
 
480
                break;
-
 
481
            case IPC_PHONE_SLAMMED:
-
 
482
                printf("slammed by: %P ",
-
 
483
                       task->phones[i].callee);
-
 
484
                break;
-
 
485
            case IPC_PHONE_HUNGUP:
-
 
486
                printf("hung up - was: %P ",
-
 
487
                       task->phones[i].callee);
-
 
488
                break;
-
 
489
            default:
-
 
490
                break;
-
 
491
            }
-
 
492
            printf("active: %d\n", atomic_get(&task->phones[i].active_calls));
-
 
493
        }
-
 
494
        spinlock_unlock(&task->phones[i].lock);
-
 
495
    }
-
 
496
 
-
 
497
 
-
 
498
    /* Print answerbox - calls */
-
 
499
    spinlock_lock(&task->answerbox.lock);
-
 
500
    printf("ABOX - CALLS:\n");
-
 
501
    for (tmp=task->answerbox.calls.next; tmp != &task->answerbox.calls;tmp = tmp->next) {
-
 
502
        call = list_get_instance(tmp, call_t, link);
-
 
503
        printf("Callid: %P Srctask:%lld M:%d A1:%d A2:%d A3:%d Flags:%x\n",call,
-
 
504
               call->sender->taskid, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
-
 
505
               IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), call->flags);
-
 
506
    }
-
 
507
    /* Print answerbox - calls */
-
 
508
    printf("ABOX - DISPATCHED CALLS:\n");
-
 
509
    for (tmp=task->answerbox.dispatched_calls.next;
-
 
510
         tmp != &task->answerbox.dispatched_calls;
-
 
511
         tmp = tmp->next) {
-
 
512
        call = list_get_instance(tmp, call_t, link);
-
 
513
        printf("Callid: %P Srctask:%lld M:%d A1:%d A2:%d A3:%d Flags:%x\n",call,
-
 
514
               call->sender->taskid, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
-
 
515
               IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), call->flags);
-
 
516
    }
-
 
517
    /* Print answerbox - calls */
-
 
518
    printf("ABOX - ANSWERS:\n");
-
 
519
    for (tmp=task->answerbox.answers.next; tmp != &task->answerbox.answers; tmp = tmp->next) {
-
 
520
        call = list_get_instance(tmp, call_t, link);
-
 
521
        printf("Callid:%P M:%d A1:%d A2:%d A3:%d Flags:%x\n",call,
-
 
522
               IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
-
 
523
               IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), call->flags);
-
 
524
    }
-
 
525
 
-
 
526
    spinlock_unlock(&task->answerbox.lock);
-
 
527
    spinlock_unlock(&task->lock);
-
 
528
}