Ignore:
File:
1 edited

Legend:

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

    rc713aa56 r287e83f  
    6262
    6363static slab_cache_t *ipc_call_slab;
    64 static slab_cache_t *ipc_answerbox_slab;
    6564
    6665/** Initialize a call structure.
     
    9796}
    9897
     98/** Initialize a statically allocated call structure.
     99 *
     100 * @param call          Statically allocated kernel call structure to be
     101 *                      initialized.
     102 */
     103void ipc_call_static_init(call_t *call)
     104{
     105        _ipc_call_init(call);
     106        call->flags |= IPC_CALL_STATIC_ALLOC;
     107}
     108
    99109/** Deallocate a call structure.
    100110 *
     
    103113void ipc_call_free(call_t *call)
    104114{
     115        ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
    105116        /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
    106117        if (call->buffer)
     
    119130        spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
    120131        waitq_initialize(&box->wq);
    121         link_initialize(&box->sync_box_link);
    122132        list_initialize(&box->connected_phones);
    123133        list_initialize(&box->calls);
     
    169179int ipc_call_sync(phone_t *phone, call_t *request)
    170180{
    171         answerbox_t *sync_box;
    172         ipl_t ipl;
    173 
    174         sync_box = slab_alloc(ipc_answerbox_slab, 0);
    175         ipc_answerbox_init(sync_box, TASK);
    176 
    177         /*
    178          * Put the answerbox on the TASK's list of synchronous answerboxes so
    179          * that it can be cleaned up if the call is interrupted.
    180          */
    181         ipl = interrupts_disable();
    182         spinlock_lock(&TASK->lock);
    183         list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
    184         spinlock_unlock(&TASK->lock);
    185         interrupts_restore(ipl);
     181        answerbox_t sync_box;
     182
     183        ipc_answerbox_init(&sync_box, TASK);
    186184
    187185        /* We will receive data in a special box. */
    188         request->callerbox = sync_box;
     186        request->callerbox = &sync_box;
    189187
    190188        ipc_call(phone, request);
    191         if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
    192             SYNCH_FLAGS_INTERRUPTIBLE)) {
    193                 /* The answerbox and the call will be freed by ipc_cleanup(). */
     189        if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT,
     190            SYNCH_FLAGS_INTERRUPTIBLE))
    194191                return EINTR;
    195         }
    196 
    197         /*
    198          * The answer arrived without interruption so we can remove the
    199          * answerbox from the TASK's list of synchronous answerboxes.
    200          */
    201         (void) interrupts_disable();
    202         spinlock_lock(&TASK->lock);
    203         list_remove(&sync_box->sync_box_link);
    204         spinlock_unlock(&TASK->lock);
    205         interrupts_restore(ipl);
    206 
    207         slab_free(ipc_answerbox_slab, sync_box);
    208192        return EOK;
    209193}
     
    212196 *
    213197 * @param call          Call structure to be answered.
    214  * @param selflocked    If true, then TASK->answebox is locked.
    215  */
    216 static void _ipc_answer_free_call(call_t *call, bool selflocked)
     198 */
     199static void _ipc_answer_free_call(call_t *call)
    217200{
    218201        answerbox_t *callerbox = call->callerbox;
    219         bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));
    220202
    221203        call->flags |= IPC_CALL_ANSWERED;
     
    228210        }
    229211
    230         if (do_lock)
    231                 spinlock_lock(&callerbox->lock);
     212        spinlock_lock(&callerbox->lock);
    232213        list_append(&call->link, &callerbox->answers);
    233         if (do_lock)
    234                 spinlock_unlock(&callerbox->lock);
     214        spinlock_unlock(&callerbox->lock);
    235215        waitq_wakeup(&callerbox->wq, WAKEUP_FIRST);
    236216}
     
    248228        spinlock_unlock(&box->lock);
    249229        /* Send back answer */
    250         _ipc_answer_free_call(call, false);
     230        _ipc_answer_free_call(call);
    251231}
    252232
     
    265245        atomic_inc(&phone->active_calls);
    266246        IPC_SET_RETVAL(call->data, err);
    267         _ipc_answer_free_call(call, false);
     247        _ipc_answer_free_call(call);
    268248}
    269249
     
    304284                if (call->flags & IPC_CALL_FORWARDED) {
    305285                        IPC_SET_RETVAL(call->data, EFORWARD);
    306                         _ipc_answer_free_call(call, false);
     286                        _ipc_answer_free_call(call);
    307287                } else {
    308288                        if (phone->state == IPC_PHONE_HUNGUP)
     
    459439
    460440                IPC_SET_RETVAL(call->data, EHANGUP);
    461                 _ipc_answer_free_call(call, true);
     441                _ipc_answer_free_call(call);
    462442        }
    463443}
     
    540520        int i;
    541521        call_t *call;
    542         ipl_t ipl;
    543522
    544523        /* Disconnect all our phones ('ipc_phone_hangup') */
     
    566545        spinlock_unlock(&TASK->answerbox.lock);
    567546       
    568         /* Wait for all answers to interrupted synchronous calls to arrive */
    569         ipl = interrupts_disable();
    570         while (!list_empty(&TASK->sync_box_head)) {
    571                 answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
    572                     answerbox_t, sync_box_link);
    573 
    574                 list_remove(&box->sync_box_link);
    575                 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
    576                     SYNCH_FLAGS_NONE);
    577                 ipc_call_free(call);
    578                 slab_free(ipc_answerbox_slab, box);
    579         }
    580         interrupts_restore(ipl);
    581 
    582         /* Wait for all answers to asynchronous calls to arrive */
     547        /* Wait for all async answers to arrive */
    583548        while (1) {
    584549                /* Go through all phones, until all are FREE... */
     
    587552                for (i = 0; i < IPC_MAX_PHONES; i++) {
    588553                        if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
    589                             atomic_get(&TASK->phones[i].active_calls) == 0) {
     554                            atomic_get(&TASK->phones[i].active_calls) == 0)
    590555                                TASK->phones[i].state = IPC_PHONE_FREE;
    591                                 TASK->phones[i].callee = NULL;
    592                         }
    593556                       
    594557                        /* Just for sure, we might have had some
     
    611574                ASSERT((call->flags & IPC_CALL_ANSWERED) ||
    612575                    (call->flags & IPC_CALL_NOTIF));
     576                ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
    613577               
    614578                /*
     
    629593        ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL,
    630594            NULL, 0);
    631         ipc_answerbox_slab = slab_cache_create("ipc_answerbox",
    632             sizeof(answerbox_t), 0, NULL, NULL, 0);
    633595}
    634596
Note: See TracChangeset for help on using the changeset viewer.