Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/ipc.c

    rcd529c4 rf97f1e51  
    7171{
    7272        memsetb(call, sizeof(*call), 0);
     73        call->callerbox = &TASK->answerbox;
    7374        call->sender = TASK;
    7475        call->buffer = NULL;
     
    119120        irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock");
    120121        waitq_initialize(&box->wq);
     122        link_initialize(&box->sync_box_link);
    121123        list_initialize(&box->connected_phones);
    122124        list_initialize(&box->calls);
     
    161163}
    162164
     165/** Helper function to facilitate synchronous calls.
     166 *
     167 * @param phone   Destination kernel phone structure.
     168 * @param request Call structure with request.
     169 *
     170 * @return EOK on success or EINTR if the sleep was interrupted.
     171 *
     172 */
     173int ipc_call_sync(phone_t *phone, call_t *request)
     174{
     175        answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0);
     176        ipc_answerbox_init(sync_box, TASK);
     177       
     178        /*
     179         * Put the answerbox on the TASK's list of synchronous answerboxes so
     180         * that it can be cleaned up if the call is interrupted.
     181         */
     182        irq_spinlock_lock(&TASK->lock, true);
     183        list_append(&sync_box->sync_box_link, &TASK->sync_boxes);
     184        irq_spinlock_unlock(&TASK->lock, true);
     185       
     186        /* We will receive data in a special box. */
     187        request->callerbox = sync_box;
     188       
     189        ipc_call(phone, request);
     190        if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
     191            SYNCH_FLAGS_INTERRUPTIBLE)) {
     192                /* The answerbox and the call will be freed by ipc_cleanup(). */
     193                return EINTR;
     194        }
     195       
     196        /*
     197         * The answer arrived without interruption so we can remove the
     198         * answerbox from the TASK's list of synchronous answerboxes.
     199         */
     200        irq_spinlock_lock(&TASK->lock, true);
     201        list_remove(&sync_box->sync_box_link);
     202        irq_spinlock_unlock(&TASK->lock, true);
     203       
     204        slab_free(ipc_answerbox_slab, sync_box);
     205        return EOK;
     206}
     207
    163208/** Answer a message which was not dispatched and is not listed in any queue.
    164209 *
     
    169214static void _ipc_answer_free_call(call_t *call, bool selflocked)
    170215{
    171         answerbox_t *callerbox = &call->sender->answerbox;
     216        answerbox_t *callerbox = call->callerbox;
    172217        bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));
    173218       
     
    561606        ipc_cleanup_call_list(&TASK->answerbox.calls);
    562607        irq_spinlock_unlock(&TASK->answerbox.lock, true);
     608       
     609        /* Wait for all answers to interrupted synchronous calls to arrive */
     610        ipl_t ipl = interrupts_disable();
     611        while (!list_empty(&TASK->sync_boxes)) {
     612                answerbox_t *box = list_get_instance(
     613                    list_first(&TASK->sync_boxes), answerbox_t, sync_box_link);
     614               
     615                list_remove(&box->sync_box_link);
     616                call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
     617                    SYNCH_FLAGS_NONE);
     618                ipc_call_free(call);
     619                slab_free(ipc_answerbox_slab, box);
     620        }
     621        interrupts_restore(ipl);
    563622       
    564623        /* Wait for all answers to asynchronous calls to arrive */
Note: See TracChangeset for help on using the changeset viewer.