Changeset 924c2530 in mainline for kernel/generic/src/ipc/sysipc.c


Ignore:
Timestamp:
2012-08-15T12:49:22Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
691d8d8
Parents:
9a82ac1
Message:

Give each system IPC method its dedicated request preprocess hook.

File:
1 edited

Legend:

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

    r9a82ac1 r924c2530  
    491491}
    492492
     493static int r_preprocess_m_connection_clone(call_t *call, phone_t *phone)
     494{
     495        phone_t *cloned_phone;
     496
     497        if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
     498                return ENOENT;
     499               
     500        phones_lock(cloned_phone, phone);
     501               
     502        if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
     503            phone->state != IPC_PHONE_CONNECTED) {
     504                phones_unlock(cloned_phone, phone);
     505                return EINVAL;
     506        }
     507               
     508        /*
     509         * We can be pretty sure now that both tasks exist and we are
     510         * connected to them. As we continue to hold the phone locks,
     511         * we are effectively preventing them from finishing their
     512         * potential cleanup.
     513         *
     514         */
     515        int newphid = phone_alloc(phone->callee->task);
     516        if (newphid < 0) {
     517                phones_unlock(cloned_phone, phone);
     518                return ELIMIT;
     519        }
     520               
     521        ipc_phone_connect(&phone->callee->task->phones[newphid],
     522            cloned_phone->callee);
     523        phones_unlock(cloned_phone, phone);
     524               
     525        /* Set the new phone for the callee. */
     526        IPC_SET_ARG1(call->data, newphid);
     527
     528        return EOK;
     529}
     530
     531static int r_preprocess_m_clone_establish(call_t *call, phone_t *phone)
     532{
     533        IPC_SET_ARG5(call->data, (sysarg_t) phone);
     534
     535        return EOK;     
     536}
     537
     538static int r_preprocess_m_connect_me_to(call_t *call, phone_t *phone)
     539{
     540        int newphid = phone_alloc(TASK);
     541
     542        if (newphid < 0)
     543                return ELIMIT;
     544               
     545        /* Set arg5 for server */
     546        IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
     547        call->flags |= IPC_CALL_CONN_ME_TO;
     548        call->priv = newphid;
     549
     550        return EOK;
     551}
     552
     553static int r_preprocess_m_share_out(call_t *call, phone_t *phone)
     554{
     555        size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
     556
     557        if (!size)
     558                return EPERM;
     559        IPC_SET_ARG2(call->data, size);
     560
     561        return EOK;
     562}
     563
     564static int r_preprocess_m_data_read(call_t *call, phone_t *phone)
     565{
     566        size_t size = IPC_GET_ARG2(call->data);
     567
     568        if (size > DATA_XFER_LIMIT) {
     569                int flags = IPC_GET_ARG3(call->data);
     570
     571                if (flags & IPC_XF_RESTRICT)
     572                        IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
     573                else
     574                        return ELIMIT;
     575        }
     576
     577        return EOK;
     578}
     579
     580static int r_preprocess_m_data_write(call_t *call, phone_t *phone)
     581{
     582        uintptr_t src = IPC_GET_ARG1(call->data);
     583        size_t size = IPC_GET_ARG2(call->data);
     584
     585        if (size > DATA_XFER_LIMIT) {
     586                int flags = IPC_GET_ARG3(call->data);
     587
     588                if (flags & IPC_XF_RESTRICT) {
     589                        size = DATA_XFER_LIMIT;
     590                        IPC_SET_ARG2(call->data, size);
     591                } else
     592                        return ELIMIT;
     593        }
     594
     595        call->buffer = (uint8_t *) malloc(size, 0);
     596        int rc = copy_from_uspace(call->buffer, (void *) src, size);
     597        if (rc != 0) {
     598                free(call->buffer);
     599                return rc;
     600        }
     601               
     602        return EOK;
     603}
     604
     605static int r_preprocess_m_state_change_authorize(call_t *call, phone_t *phone)
     606{
     607        phone_t *sender_phone;
     608        task_t *other_task_s;
     609
     610        if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
     611                return ENOENT;
     612
     613        mutex_lock(&sender_phone->lock);
     614        if (sender_phone->state != IPC_PHONE_CONNECTED) {
     615                mutex_unlock(&sender_phone->lock);
     616                return EINVAL;
     617        }
     618
     619        other_task_s = sender_phone->callee->task;
     620
     621        mutex_unlock(&sender_phone->lock);
     622
     623        /* Remember the third party task hash. */
     624        IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
     625
     626        return EOK;
     627}
     628
    493629/** Called before the request is sent.
    494630 *
     
    501637static int request_preprocess(call_t *call, phone_t *phone)
    502638{
     639        int rc = EOK;
     640
    503641        switch (IPC_GET_IMETHOD(call->data)) {
    504         case IPC_M_CONNECTION_CLONE: {
    505                 phone_t *cloned_phone;
    506                 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
    507                         return ENOENT;
    508                
    509                 phones_lock(cloned_phone, phone);
    510                
    511                 if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    512                     phone->state != IPC_PHONE_CONNECTED) {
    513                         phones_unlock(cloned_phone, phone);
    514                         return EINVAL;
    515                 }
    516                
    517                 /*
    518                  * We can be pretty sure now that both tasks exist and we are
    519                  * connected to them. As we continue to hold the phone locks,
    520                  * we are effectively preventing them from finishing their
    521                  * potential cleanup.
    522                  *
    523                  */
    524                 int newphid = phone_alloc(phone->callee->task);
    525                 if (newphid < 0) {
    526                         phones_unlock(cloned_phone, phone);
    527                         return ELIMIT;
    528                 }
    529                
    530                 ipc_phone_connect(&phone->callee->task->phones[newphid],
    531                     cloned_phone->callee);
    532                 phones_unlock(cloned_phone, phone);
    533                
    534                 /* Set the new phone for the callee. */
    535                 IPC_SET_ARG1(call->data, newphid);
    536                 break;
    537         }
     642        case IPC_M_CONNECTION_CLONE:
     643                rc = r_preprocess_m_connection_clone(call, phone);
     644                break;
    538645        case IPC_M_CLONE_ESTABLISH:
    539                 IPC_SET_ARG5(call->data, (sysarg_t) phone);
    540                 break;
    541         case IPC_M_CONNECT_ME_TO: {
    542                 int newphid = phone_alloc(TASK);
    543                 if (newphid < 0)
    544                         return ELIMIT;
    545                
    546                 /* Set arg5 for server */
    547                 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
    548                 call->flags |= IPC_CALL_CONN_ME_TO;
    549                 call->priv = newphid;
    550                 break;
    551         }
    552         case IPC_M_SHARE_OUT: {
    553                 size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
    554                 if (!size)
    555                         return EPERM;
    556                
    557                 IPC_SET_ARG2(call->data, size);
    558                 break;
    559         }
    560         case IPC_M_DATA_READ: {
    561                 size_t size = IPC_GET_ARG2(call->data);
    562                 if (size > DATA_XFER_LIMIT) {
    563                         int flags = IPC_GET_ARG3(call->data);
    564                         if (flags & IPC_XF_RESTRICT)
    565                                 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
    566                         else
    567                                 return ELIMIT;
    568                 }
    569                 break;
    570         }
    571         case IPC_M_DATA_WRITE: {
    572                 uintptr_t src = IPC_GET_ARG1(call->data);
    573                 size_t size = IPC_GET_ARG2(call->data);
    574                
    575                 if (size > DATA_XFER_LIMIT) {
    576                         int flags = IPC_GET_ARG3(call->data);
    577                         if (flags & IPC_XF_RESTRICT) {
    578                                 size = DATA_XFER_LIMIT;
    579                                 IPC_SET_ARG2(call->data, size);
    580                         } else
    581                                 return ELIMIT;
    582                 }
    583                
    584                 call->buffer = (uint8_t *) malloc(size, 0);
    585                 int rc = copy_from_uspace(call->buffer, (void *) src, size);
    586                 if (rc != 0) {
    587                         free(call->buffer);
    588                         return rc;
    589                 }
    590                
    591                 break;
    592         }
    593         case IPC_M_STATE_CHANGE_AUTHORIZE: {
    594                 phone_t *sender_phone;
    595                 task_t *other_task_s;
    596 
    597                 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
    598                         return ENOENT;
    599 
    600                 mutex_lock(&sender_phone->lock);
    601                 if (sender_phone->state != IPC_PHONE_CONNECTED) {
    602                         mutex_unlock(&sender_phone->lock);
    603                         return EINVAL;
    604                 }
    605 
    606                 other_task_s = sender_phone->callee->task;
    607 
    608                 mutex_unlock(&sender_phone->lock);
    609 
    610                 /* Remember the third party task hash. */
    611                 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
    612                 break;
    613         }
     646                rc = r_preprocess_m_clone_establish(call, phone);
     647                break;
     648        case IPC_M_CONNECT_ME_TO:
     649                rc = r_preprocess_m_connect_me_to(call, phone);
     650                break;
     651        case IPC_M_SHARE_OUT:
     652                rc = r_preprocess_m_share_out(call, phone);
     653                break;
     654        case IPC_M_DATA_READ:
     655                rc = r_preprocess_m_data_read(call, phone);
     656                break;
     657        case IPC_M_DATA_WRITE:
     658                rc = r_preprocess_m_data_write(call, phone);
     659                break;
     660        case IPC_M_STATE_CHANGE_AUTHORIZE:
     661                rc = r_preprocess_m_state_change_authorize(call, phone);
     662                break;
    614663#ifdef CONFIG_UDEBUG
    615664        case IPC_M_DEBUG:
    616                 return udebug_request_preprocess(call, phone);
     665                rc = udebug_request_preprocess(call, phone);
     666                break;
    617667#endif
    618668        default:
     
    620670        }
    621671       
    622         return 0;
     672        return rc;
    623673}
    624674
Note: See TracChangeset for help on using the changeset viewer.