Changeset 2c0e5d2 in mainline for kernel/generic/src/ipc/sysipc.c


Ignore:
Timestamp:
2009-05-19T21:47:00Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
27fd651
Parents:
0c2eee0
Message:

Add IPC_M_CONNECTION_CLONE and IPC_M_CONNECT_ME.

File:
1 edited

Legend:

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

    r0c2eee0 r2c0e5d2  
    9494{
    9595        switch (method) {
     96        case IPC_M_CONNECTION_CLONE:
     97        case IPC_M_CONNECT_ME:
    9698        case IPC_M_PHONE_HUNGUP:
    9799                /* This message is meant only for the original recipient. */
     
    141143{
    142144        switch (IPC_GET_METHOD(call->data)) {
     145        case IPC_M_CONNECTION_CLONE:
     146        case IPC_M_CONNECT_ME:
    143147        case IPC_M_CONNECT_TO_ME:
    144148        case IPC_M_CONNECT_ME_TO:
     
    183187                return 0;
    184188
    185         if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
     189        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
     190                phoneid = IPC_GET_ARG1(*olddata);
     191                phone_t *phone = &TASK->phones[phoneid];
     192                if (IPC_GET_RETVAL(answer->data) != EOK) {
     193                        /*
     194                         * The recipient of the cloned phone rejected the offer.
     195                         * In this case, the connection was established at the
     196                         * request time and therefore we need to slam the phone.
     197                         * We don't merely hangup as that would result in
     198                         * sending IPC_M_HUNGUP to the third party on the
     199                         * other side of the cloned phone.
     200                         */
     201                        mutex_lock(&phone->lock);
     202                        if (phone->state == IPC_PHONE_CONNECTED) {
     203                                spinlock_lock(&phone->callee->lock);
     204                                list_remove(&phone->link);
     205                                phone->state = IPC_PHONE_SLAMMED;
     206                                spinlock_unlock(&phone->callee->lock);
     207                        }
     208                        mutex_unlock(&phone->lock);
     209                }
     210        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
     211                phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
     212                if (IPC_GET_RETVAL(answer->data) != EOK) {
     213                        /*
     214                         * The other party on the cloned phoned rejected our
     215                         * request for connection on the protocol level.
     216                         * We need to break the connection without sending
     217                         * IPC_M_HUNGUP back.
     218                         */
     219                        mutex_lock(&phone->lock);
     220                        if (phone->state == IPC_PHONE_CONNECTED) {
     221                                spinlock_lock(&phone->callee->lock);
     222                                list_remove(&phone->link);
     223                                phone->state = IPC_PHONE_SLAMMED;
     224                                spinlock_unlock(&phone->callee->lock);
     225                        }
     226                        mutex_unlock(&phone->lock);
     227                }
     228        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    186229                phoneid = IPC_GET_ARG5(*olddata);
    187                 if (IPC_GET_RETVAL(answer->data)) {
     230                if (IPC_GET_RETVAL(answer->data) != EOK) {
    188231                        /* The connection was not accepted */
    189232                        phone_dealloc(phoneid);
     
    197240        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
    198241                /* If the users accepted call, connect */
    199                 if (!IPC_GET_RETVAL(answer->data)) {
     242                if (IPC_GET_RETVAL(answer->data) == EOK) {
    200243                        ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata),
    201244                            &TASK->answerbox);
     
    309352
    310353        switch (IPC_GET_METHOD(call->data)) {
     354        case IPC_M_CONNECTION_CLONE: {
     355                phone_t *cloned_phone;
     356                GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
     357                    return ENOENT);
     358                if (cloned_phone < phone) {
     359                        mutex_lock(&cloned_phone->lock);
     360                        mutex_lock(&phone->lock);
     361                } else {
     362                        mutex_lock(&phone->lock);
     363                        mutex_lock(&cloned_phone->lock);
     364                }
     365                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
     366                    phone->state != IPC_PHONE_CONNECTED) {
     367                        mutex_unlock(&cloned_phone->lock);
     368                        mutex_unlock(&phone->lock);
     369                        return EINVAL;
     370                }
     371                /*
     372                 * We can be pretty sure now that both tasks exist and we are
     373                 * connected to them. As we continue to hold the phone locks,
     374                 * we are effectively preventing them from finishing their
     375                 * potential cleanup.
     376                 */
     377                newphid = phone_alloc(phone->callee->task);
     378                if (newphid < 0) {
     379                        mutex_unlock(&cloned_phone->lock);
     380                        mutex_unlock(&phone->lock);
     381                        return ELIMIT;
     382                }
     383                ipc_phone_connect(&phone->callee->task->phones[newphid],
     384                    cloned_phone->callee);
     385                mutex_unlock(&cloned_phone->lock);
     386                mutex_unlock(&phone->lock);
     387                /* Set the new phone for the callee. */
     388                IPC_SET_ARG1(call->data, newphid);
     389                break;
     390        }
     391        case IPC_M_CONNECT_ME:
     392                IPC_SET_ARG5(call->data, (unative_t) phone);
     393                break;
    311394        case IPC_M_CONNECT_ME_TO:
    312                 newphid = phone_alloc();
     395                newphid = phone_alloc(TASK);
    313396                if (newphid < 0)
    314397                        return ELIMIT;
     
    400483
    401484        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    402                 phoneid = phone_alloc();
     485                phoneid = phone_alloc(TASK);
    403486                if (phoneid < 0) { /* Failed to allocate phone */
    404487                        IPC_SET_RETVAL(call->data, ELIMIT);
Note: See TracChangeset for help on using the changeset viewer.