Changeset eb3d379 in mainline for generic/src/ipc/ipc.c


Ignore:
Timestamp:
2006-06-04T15:58:01Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8adafa0
Parents:
7669bcf
Message:

Slightly remodelled ipc hangups to facilitate correct cleanup.
Doc updates for frame allocator.

File:
1 edited

Legend:

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

    r7669bcf reb3d379  
    112112
    113113        ASSERT(!phone->callee);
    114         phone->busy = IPC_BUSY_CONNECTED;
     114        phone->state = IPC_PHONE_CONNECTED;
    115115        phone->callee = box;
    116116
     
    128128        spinlock_initialize(&phone->lock, "phone_lock");
    129129        phone->callee = NULL;
    130         phone->busy = IPC_BUSY_FREE;
     130        phone->state = IPC_PHONE_FREE;
    131131        atomic_set(&phone->active_calls, 0);
    132132}
     
    185185        call->data.phone = phone;
    186186        atomic_inc(&phone->active_calls);
    187         if (phone->busy == IPC_BUSY_CONNECTED)
    188                 IPC_SET_RETVAL(call->data, EHANGUP);
    189         else
    190                 IPC_SET_RETVAL(call->data, ENOENT);
    191 
     187        IPC_SET_RETVAL(call->data, err);
    192188        _ipc_answer_free_call(call);
    193189}
     
    217213
    218214        spinlock_lock(&phone->lock);
    219 
    220         box = phone->callee;
    221         if (!box) {
    222                 /* Trying to send over disconnected phone */
     215        if (phone->state != IPC_PHONE_CONNECTED) {
    223216                spinlock_unlock(&phone->lock);
    224217                if (call->flags & IPC_CALL_FORWARDED) {
    225218                        IPC_SET_RETVAL(call->data, EFORWARD);
    226219                        _ipc_answer_free_call(call);
    227                 } else { /* Simulate sending back a message */
    228                         if (phone->busy == IPC_BUSY_CONNECTED)
     220                } else {
     221                        if (phone->state == IPC_PHONE_HUNGUP)
    229222                                ipc_backsend_err(phone, call, EHANGUP);
    230223                        else
    231224                                ipc_backsend_err(phone, call, ENOENT);
    232225                }
    233 
    234226                return ENOENT;
    235227        }
     228        box = phone->callee;
    236229        _ipc_call(phone, box, call);
    237230       
     
    242235/** Disconnect phone from answerbox
    243236 *
    244  * It is allowed to call disconnect on already disconnected phone
    245  *
     237 * This call leaves the phone in HUNGUP state. The change to 'free' is done
     238 * lazily later.
     239 *
     240 * @param phone Phone to be hung up
     241 * @param aggressive If false, the phone is only marked hungup, and all
     242 *              messages are allowed to complete.
     243 *              If true, all messages in all queues are discarded. There
     244 *              may still be some messages that will be 'in-transit' on
     245 *              other CPU.
     246 *             
    246247 * @return 0 - phone disconnected, -1 - the phone was already disconnected
    247248 */
    248 int ipc_phone_hangup(phone_t *phone)
     249int ipc_phone_hangup(phone_t *phone, int aggressive)
    249250{
    250251        answerbox_t *box;
     
    252253       
    253254        spinlock_lock(&phone->lock);
     255        if (phone->state == IPC_PHONE_FREE || phone->state ==IPC_PHONE_HUNGUP \
     256            || phone->state == IPC_PHONE_CONNECTING) {
     257                spinlock_unlock(&phone->lock);
     258                return -1;
     259        }
    254260        box = phone->callee;
    255         if (!box) {
    256                 if (phone->busy == IPC_BUSY_CONNECTING) {
    257                         spinlock_unlock(&phone->lock);
    258                         return -1;
     261        if (phone->state != IPC_PHONE_SLAMMED) {
     262                /* Remove myself from answerbox */
     263                spinlock_lock(&box->lock);
     264                list_remove(&phone->list);
     265                spinlock_unlock(&box->lock);
     266
     267                if (phone->state != IPC_PHONE_SLAMMED) {
     268                        call = ipc_call_alloc(0);
     269                        IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
     270                        call->flags |= IPC_CALL_DISCARD_ANSWER;
     271                        _ipc_call(phone, box, call);
    259272                }
    260                 /* Already disconnected phone */
    261                 phone->busy = IPC_BUSY_FREE;
    262                 spinlock_unlock(&phone->lock);
    263                 return 0;
    264         }
    265 
    266         spinlock_lock(&box->lock);
    267         list_remove(&phone->list);
    268         phone->callee = NULL;
    269         spinlock_unlock(&box->lock);
    270 
    271         call = ipc_call_alloc(0);
    272         IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
    273         call->flags |= IPC_CALL_DISCARD_ANSWER;
    274         _ipc_call(phone, box, call);
    275 
    276         phone->busy = IPC_BUSY_FREE;
    277 
     273        }
     274
     275        if (aggressive && atomic_get(&phone->active_calls) > 0) {
     276                /* TODO: Do some stuff be VERY aggressive */
     277        }
     278
     279        phone->callee = 0;
     280       
     281        phone->state = IPC_PHONE_HUNGUP;
    278282        spinlock_unlock(&phone->lock);
    279283
     
    381385        /* Disconnect all our phones ('ipc_phone_hangup') */
    382386        for (i=0;i < IPC_MAX_PHONES; i++)
    383                 ipc_phone_hangup(&task->phones[i]);
     387                ipc_phone_hangup(&task->phones[i], 1);
    384388
    385389        /* Disconnect all connected irqs */
     
    399403               
    400404                /* Disconnect phone */
    401                 phone->callee = NULL;
     405                ASSERT(phone->state == IPC_PHONE_CONNECTED);
     406                phone->state = IPC_PHONE_SLAMMED;
    402407                list_remove(&phone->list);
    403408
     
    412417       
    413418        /* Wait for all async answers to arrive */
    414         while (atomic_get(&task->active_calls)) {
     419        while (1) {
     420                /* Go through all phones, until all are FREE... */
     421                /* Locking not needed, no one else should modify
     422                 * it, when we are in cleanup */
     423                for (i=0;i < IPC_MAX_PHONES; i++) {
     424                        if (task->phones[i].state == IPC_PHONE_HUNGUP && \
     425                            atomic_get(&task->phones[i].active_calls) == 0)
     426                                task->phones[i].state = IPC_PHONE_FREE;
     427                        if (task->phones[i].state != IPC_PHONE_FREE)
     428                                break;
     429                }
     430                /* Voila, got into cleanup */
     431                if (i == IPC_MAX_PHONES)
     432                        break;
     433               
    415434                call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
    416435                ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF));
Note: See TracChangeset for help on using the changeset viewer.