Changeset 7c7aae16 in mainline


Ignore:
Timestamp:
2006-03-19T19:42:00Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ad64a2d
Parents:
9f22213
Message:

Reduced unnecessary IPC system calls.
Allow everything to be sync & async, everything is handled using messages.

Location:
generic
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • generic/include/ipc/ipc.h

    r9f22213 r7c7aae16  
    4040#define IPC_CALL_ANSWERED       (1<<0) /**< This is answer to a call */
    4141#define IPC_CALL_STATIC_ALLOC   (1<<1) /**< This call will not be freed on error */
    42 #define IPC_CALL_DISPATCHED     (1<<2) /**< Call is in dispatch queue */
    43 #define IPC_CALL_DISCARD_ANSWER (1<<3) /**< Answer will not be passed to
     42#define IPC_CALL_DISCARD_ANSWER (1<<2) /**< Answer will not be passed to
    4443                                        * userspace, will be discarded */
    45 #define IPC_CALL_FORWARDED      (1<<4) /* Call was forwarded */
     44#define IPC_CALL_FORWARDED      (1<<3) /* Call was forwarded */
     45#define IPC_CALL_CONN_ME_TO     (1<<4) /* Identify connect_me_to */
    4646
    4747/* Flags for ipc_wait_for_call */
     
    183183        answerbox_t *callerbox;
    184184
    185         ipc_data_t data;
     185        __native private; /**< Private data to internal IPC */
     186
     187        ipc_data_t data;  /**< Data passed from/to userspace */
    186188}call_t;
    187189
     
    199201extern void task_print_list(void);
    200202extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox);
    201 
    202 extern answerbox_t *ipc_phone_0;
    203203extern void ipc_cleanup(task_t *task);
    204204extern int ipc_phone_hangup(phone_t *phone);
     205extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err);
     206
     207extern answerbox_t *ipc_phone_0;
    205208
    206209#endif
  • generic/include/ipc/sysipc.h

    r9f22213 r7c7aae16  
    4040                             __native arg1, __native arg2);
    4141__native sys_ipc_answer(__native callid, ipc_data_t *data);
    42 __native sys_ipc_connect_to_me(__native phoneid, __native arg1,
    43                                __native arg2, task_id_t *taskid);
    44 __native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid,
    45                                __native flags);
    46 __native sys_ipc_connect_me_to(__native phoneid, __native arg1,
    47                                __native arg2);
     42__native sys_ipc_wait_for_call(ipc_data_t *calldata, __native flags);
    4843__native sys_ipc_forward_fast(__native callid, __native phoneid,
    4944                              __native method, __native arg1);
  • generic/include/syscall/syscall.h

    r9f22213 r7c7aae16  
    4444        SYS_IPC_FORWARD_FAST,
    4545        SYS_IPC_WAIT,
    46         SYS_IPC_CONNECT_TO_ME,
    47         SYS_IPC_CONNECT_ME_TO,
    4846        SYS_IPC_HANGUP,
    4947        SYSCALL_END
  • generic/src/ipc/ipc.c

    r9f22213 r7c7aae16  
    146146        answerbox_t *callerbox = call->callerbox;
    147147
    148         call->flags &= ~IPC_CALL_DISPATCHED;
    149148        call->flags |= IPC_CALL_ANSWERED;
    150149
     
    167166        spinlock_unlock(&box->lock);
    168167        /* Send back answer */
     168        _ipc_answer_free_call(call);
     169}
     170
     171/** Simulate sending back a message
     172 *
     173 * Most errors are better handled by forming a normal backward
     174 * message and sending it as a normal answer.
     175 */
     176void ipc_backsend_err(phone_t *phone, call_t *call, __native err)
     177{
     178        call->data.phone = phone;
     179        atomic_inc(&phone->active_calls);
     180        if (phone->busy == IPC_BUSY_CONNECTED)
     181                IPC_SET_RETVAL(call->data, EHANGUP);
     182        else
     183                IPC_SET_RETVAL(call->data, ENOENT);
     184
    169185        _ipc_answer_free_call(call);
    170186}
     
    201217                if (call->flags & IPC_CALL_FORWARDED) {
    202218                        IPC_SET_RETVAL(call->data, EFORWARD);
    203                 } else { /* Simulate sending a message */
    204                         call->data.phone = phone;
    205                         atomic_inc(&phone->active_calls);
     219                        _ipc_answer_free_call(call);
     220                } else { /* Simulate sending back a message */
    206221                        if (phone->busy == IPC_BUSY_CONNECTED)
    207                                 IPC_SET_RETVAL(call->data, EHANGUP);
     222                                ipc_backsend_err(phone, call, EHANGUP);
    208223                        else
    209                                 IPC_SET_RETVAL(call->data, ENOENT);
     224                                ipc_backsend_err(phone, call, ENOENT);
    210225                }
    211226
    212                 _ipc_answer_free_call(call);
    213227                return ENOENT;
    214228        }
     
    308322                /* Append request to dispatch queue */
    309323                list_append(&request->list, &box->dispatched_calls);
    310                 request->flags |= IPC_CALL_DISPATCHED;
    311324        } else {
    312325                printf("WARNING: Spurious IPC wakeup.\n");
  • generic/src/ipc/ipcrsc.c

    r9f22213 r7c7aae16  
    6363 * Destroying is less frequent, this approach is taken.
    6464 *
     65 * Phone call
     66 *
     67 * *** Connect_me_to ***
     68 * The caller sends IPC_M_CONNECT_ME_TO to an answerbox. The server
     69 * receives 'phoneid' of the connecting phone as an ARG3. If it answers
     70 * with RETVAL=0, the phonecall is accepted, otherwise it is refused.
     71 *
     72 * *** Connect_to_me ***
     73 * The caller sends IPC_M_CONNECT_TO_ME, with special
     74 * The server receives an automatically
     75 * opened phoneid. If it accepts (RETVAL=0), it can use the phoneid
     76 * immediately.
     77 * Possible race condition can arise, when the client receives messages
     78 * from new connection before getting response for connect_to_me message.
     79 * Userspace should implement handshake protocol that would control it.
     80 *
    6581 * Phone hangup
    6682 *
     
    101117 *    appropriate error code (EHANGUP, EFORWARD).
    102118 *
    103  * 4) Wait for all async answers to arrive.
     119 * 4) Wait for all async answers to arrive and dispose of them.
    104120 *
    105121 */
     
    143159}
    144160
    145 /** Disconnect phone a free the slot
     161static void phone_deallocp(phone_t *phone)
     162{
     163        ASSERT(phone->busy == IPC_BUSY_CONNECTING);
     164        ASSERT(! phone->callee);
     165       
     166        /* atomic operation */
     167        phone->busy = IPC_BUSY_FREE;
     168}
     169
     170/** Free slot from a disconnected phone
    146171 *
    147172 * All already sent messages will be correctly processed
     
    149174void phone_dealloc(int phoneid)
    150175{
    151         spinlock_lock(&TASK->lock);
    152 
    153         ASSERT(TASK->phones[phoneid].busy == IPC_BUSY_CONNECTING);
    154         ASSERT(! TASK->phones[phoneid].callee);
    155 
    156         TASK->phones[phoneid].busy = IPC_BUSY_FREE;
    157         spinlock_unlock(&TASK->lock);
     176        phone_deallocp(&TASK->phones[phoneid]);
    158177}
    159178
  • generic/src/ipc/sysipc.c

    r9f22213 r7c7aae16  
    4848}
    4949
    50 #define STRUCT_TO_USPACE(dst,src) copy_to_uspace(dst,src,sizeof(*src))
     50#define STRUCT_TO_USPACE(dst,src) copy_to_uspace(dst,src,sizeof(*(src)))
    5151
    5252/** Return true if the method is a system method */
     
    106106                        phone_dealloc(phoneid);
    107107                } else {
    108                                 /* The connection was accepted */
     108                        /* The connection was accepted */
    109109                        phone_connect(phoneid,&answer->sender->answerbox);
     110                        /* Set 'phone identification' as arg3 of response */
     111                        IPC_SET_ARG3(answer->data, (__native)&TASK->phones[phoneid]);
    110112                }
    111113        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
     
    118120}
    119121
     122/** Called before the request is sent
     123 *
     124 * @return 0 - no error, -1 - report error to user
     125 */
     126static int request_preprocess(call_t *call)
     127{
     128        int newphid;
     129
     130        switch (IPC_GET_METHOD(call->data)) {
     131        case IPC_M_CONNECT_ME_TO:
     132                newphid = phone_alloc();
     133                if (newphid < 0)
     134                        return ELIMIT;
     135                /* Set arg3 for server */
     136                IPC_SET_ARG3(call->data, (__native)&TASK->phones[newphid]);
     137                call->flags |= IPC_CALL_CONN_ME_TO;
     138                call->private = newphid;
     139                break;
     140        default:
     141                break;
     142        }
     143        return 0;
     144}
     145
    120146/****************************************************/
    121147/* Functions called to process received call/answer
     
    124150
    125151/** Do basic kernel processing of received call answer */
    126 static int process_answer(answerbox_t *box,call_t *call)
     152static void process_answer(call_t *call)
    127153{
    128154        if (IPC_GET_RETVAL(call->data) == EHANGUP && \
    129155            call->flags & IPC_CALL_FORWARDED)
    130156                IPC_SET_RETVAL(call->data, EFORWARD);
    131         return 0;
     157
     158        if (call->flags & IPC_CALL_CONN_ME_TO) {
     159                if (IPC_GET_RETVAL(call->data))
     160                        phone_dealloc(call->private);
     161                else
     162                        IPC_SET_ARG3(call->data, call->private);
     163        }
    132164}
    133165
     
    162194        call_t call;
    163195        phone_t *phone;
    164 
    165         if (is_system_method(method))
    166                 return EPERM;
     196        int res;
    167197
    168198        GET_CHECK_PHONE(phone, phoneid, return ENOENT);
     
    171201        IPC_SET_METHOD(call.data, method);
    172202        IPC_SET_ARG1(call.data, arg1);
    173        
    174         ipc_call_sync(phone, &call);
    175 
     203
     204        if (!(res=request_preprocess(&call))) {
     205                ipc_call_sync(phone, &call);
     206                process_answer(&call);
     207        } else
     208                IPC_SET_RETVAL(call.data, res);
    176209        STRUCT_TO_USPACE(&data->args, &call.data.args);
    177210
     
    185218        call_t call;
    186219        phone_t *phone;
     220        int res;
    187221
    188222        ipc_call_static_init(&call);
    189223        copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args));
    190224
    191         if (is_system_method(IPC_GET_METHOD(call.data)))
    192                 return EPERM;
    193        
    194225        GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    195226
    196         ipc_call_sync(phone, &call);
     227        if (!(res=request_preprocess(&call))) {
     228                ipc_call_sync(phone, &call);
     229                process_answer(&call);
     230        } else
     231                IPC_SET_RETVAL(call.data, res);
    197232
    198233        STRUCT_TO_USPACE(&reply->args, &call.data.args);
     
    224259        call_t *call;
    225260        phone_t *phone;
    226 
    227         if (is_system_method(method))
    228                 return IPC_CALLRET_FATAL;
     261        int res;
    229262
    230263        if (check_call_limit())
    231264                return IPC_CALLRET_TEMPORARY;
    232265
    233         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
     266        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
    234267
    235268        call = ipc_call_alloc();
     
    238271        IPC_SET_ARG2(call->data, arg2);
    239272
    240         ipc_call(phone, call);
     273        if (!(res=request_preprocess(call)))
     274                ipc_call(phone, call);
     275        else
     276                ipc_backsend_err(phone, call, res);
    241277
    242278        return (__native) call;
     
    251287        call_t *call;
    252288        phone_t *phone;
     289        int res;
    253290
    254291        if (check_call_limit())
    255292                return IPC_CALLRET_TEMPORARY;
    256293
    257         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
     294        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
    258295
    259296        call = ipc_call_alloc();
    260297        copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args));
    261 
    262         if (is_system_method(IPC_GET_METHOD(call->data))) {
    263                 ipc_call_free(call);
    264                 return EPERM;
    265         }
    266        
    267         ipc_call(phone, call);
     298        if (!(res=request_preprocess(call)))
     299                ipc_call(phone, call);
     300        else
     301                ipc_backsend_err(phone, call, res);
    268302
    269303        return (__native) call;
     
    305339         */
    306340        if (is_system_method(IPC_GET_METHOD(call->data))) {
     341                if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
     342                        phone_dealloc(IPC_GET_ARG3(call->data));
     343
    307344                IPC_SET_ARG1(call->data, method);
    308345                IPC_SET_ARG2(call->data, arg1);
     
    366403}
    367404
    368 /** Ask the other side of connection to do 'callback' connection
    369  *
    370  * @return 0 if no error, error otherwise
    371  */
    372 __native sys_ipc_connect_to_me(__native phoneid, __native arg1,
    373                                __native arg2, task_id_t *taskid)
    374 {
    375         call_t call;
    376         phone_t *phone;
    377 
    378         ipc_call_static_init(&call);
    379         IPC_SET_METHOD(call.data, IPC_M_CONNECT_TO_ME);
    380         IPC_SET_ARG1(call.data, arg1);
    381         IPC_SET_ARG2(call.data, arg2);
    382        
    383         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    384 
    385         ipc_call_sync(phone, &call);
    386 
    387         if (!IPC_GET_RETVAL(call.data) && taskid)
    388                 STRUCT_TO_USPACE(taskid, &phone->callee->task->taskid);
    389 
    390         return IPC_GET_RETVAL(call.data);
    391 }
    392 
    393 /** Ask target process to connect me somewhere
    394  *
    395  * @return phoneid - on success, error otherwise
    396  */
    397 __native sys_ipc_connect_me_to(__native phoneid, __native arg1,
    398                                __native arg2)
    399 {
    400         call_t call;
    401         phone_t *phone;
    402         int newphid;
    403 
    404         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    405 
    406         newphid = phone_alloc();
    407         if (newphid < 0)
    408                 return ELIMIT;
    409 
    410         ipc_call_static_init(&call);
    411         IPC_SET_METHOD(call.data, IPC_M_CONNECT_ME_TO);
    412         IPC_SET_ARG1(call.data, arg1);
    413         IPC_SET_ARG2(call.data, arg2);
    414         IPC_SET_ARG3(call.data, (__native)&TASK->phones[newphid]);
    415 
    416         ipc_call_sync(phone, &call);
    417 
    418         if (IPC_GET_RETVAL(call.data)) { /* Connection failed */
    419                 phone_dealloc(newphid);
    420                 return IPC_GET_RETVAL(call.data);
    421         }
    422 
    423         return newphid;
    424 }
    425 
    426405/** Hang up the phone
    427  *
    428  *
    429406 *
    430407 */
     
    449426 * @return Callid, if callid & 1, then the call is answer
    450427 */
    451 __native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid,
    452                                __native flags)
    453                                              
     428__native sys_ipc_wait_for_call(ipc_data_t *calldata, __native flags)
    454429{
    455430        call_t *call;
     
    461436
    462437        if (call->flags & IPC_CALL_ANSWERED) {
    463                 if (process_answer(&TASK->answerbox, call))
    464                         goto restart;
     438                process_answer(call);
    465439
    466440                ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
     
    482456                goto restart;
    483457
    484         /* Include phone address('id') of the caller in the request */
     458        /* Include phone address('id') of the caller in the request,
     459         * copy whole call->data, not only call->data.args */
    485460        STRUCT_TO_USPACE(calldata, &call->data);
    486         if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)
    487                 STRUCT_TO_USPACE(taskid, &TASK->taskid);
    488461        return (__native)call;
    489462}
  • generic/src/syscall/syscall.c

    r9f22213 r7c7aae16  
    7777        sys_ipc_forward_fast,
    7878        sys_ipc_wait_for_call,
    79         sys_ipc_connect_to_me,
    80         sys_ipc_connect_me_to,
    8179        sys_ipc_hangup
    8280};
Note: See TracChangeset for help on using the changeset viewer.