Changeset 9f22213 in mainline


Ignore:
Timestamp:
2006-03-19T12:43:12Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7c7aae16
Parents:
b4b45210
Message:

More IPC stuff, added correct closing of connections from both sides.

Location:
generic
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • generic/include/errno.h

    rb4b45210 r9f22213  
    3838#define EFORWARD   -5  /* Forward error */
    3939#define EPERM      -6  /* Permission denied */
     40#define EHANGUP    -7  /* Answerbox closed cionnection, call sys_ipc_hangup
     41                        * to close the connection. Used by answerbox
     42                        * to close the connection.  */
    4043
    4144#endif
  • generic/include/ipc/ipc.h

    rb4b45210 r9f22213  
    3838
    3939/* Flags for calls */
    40 #define IPC_CALL_ANSWERED     (1<<0) /**< This is answer to a call */
    41 #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 */
     40#define IPC_CALL_ANSWERED       (1<<0) /**< This is answer to a call */
     41#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 */
    4343#define IPC_CALL_DISCARD_ANSWER (1<<3) /**< Answer will not be passed to
    4444                                        * userspace, will be discarded */
     45#define IPC_CALL_FORWARDED      (1<<4) /* Call was forwarded */
    4546
    4647/* Flags for ipc_wait_for_call */
     
    156157};
    157158
     159typedef enum {
     160        IPC_BUSY_FREE = 0,
     161        IPC_BUSY_CONNECTING,
     162        IPC_BUSY_CONNECTED
     163} ipc_busy_t;
     164
    158165struct phone_s {
    159166        SPINLOCK_DECLARE(lock);
    160167        link_t list;
    161168        answerbox_t *callee;
    162         int busy;
     169        ipc_busy_t busy;
    163170        atomic_t active_calls;
    164171};
     
    182189extern call_t * ipc_wait_for_call(answerbox_t *box, int flags);
    183190extern void ipc_answer(answerbox_t *box, call_t *request);
    184 extern void ipc_call(phone_t *phone, call_t *request);
     191extern int ipc_call(phone_t *phone, call_t *call);
    185192extern void ipc_call_sync(phone_t *phone, call_t *request);
    186193extern void ipc_phone_init(phone_t *phone);
     
    191198extern void ipc_call_static_init(call_t *call);
    192199extern void task_print_list(void);
    193 extern void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox);
     200extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox);
    194201
    195202extern answerbox_t *ipc_phone_0;
  • generic/src/ipc/ipc.c

    rb4b45210 r9f22213  
    105105
    106106        ASSERT(!phone->callee);
    107         phone->busy = 1;
     107        phone->busy = IPC_BUSY_CONNECTED;
    108108        phone->callee = box;
    109109
     
    121121        spinlock_initialize(&phone->lock, "phone_lock");
    122122        phone->callee = NULL;
    123         phone->busy = 0;
     123        phone->busy = IPC_BUSY_FREE;
     124        atomic_set(&phone->active_calls, 0);
    124125}
    125126
     
    172173static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
    173174{
    174         atomic_inc(&phone->active_calls);
    175         call->data.phone = phone;
     175        if (! (call->flags & IPC_CALL_FORWARDED)) {
     176                atomic_inc(&phone->active_calls);
     177                call->data.phone = phone;
     178        }
    176179
    177180        spinlock_lock(&box->lock);
     
    186189 * @param request Request to be sent
    187190 */
    188 void ipc_call(phone_t *phone, call_t *call)
     191int ipc_call(phone_t *phone, call_t *call)
    189192{
    190193        answerbox_t *box;
     
    196199                /* Trying to send over disconnected phone */
    197200                spinlock_unlock(&phone->lock);
    198 
    199                 call->data.phone = phone;
    200                 IPC_SET_RETVAL(call->data, ENOENT);
     201                if (call->flags & IPC_CALL_FORWARDED) {
     202                        IPC_SET_RETVAL(call->data, EFORWARD);
     203                } else { /* Simulate sending a message */
     204                        call->data.phone = phone;
     205                        atomic_inc(&phone->active_calls);
     206                        if (phone->busy == IPC_BUSY_CONNECTED)
     207                                IPC_SET_RETVAL(call->data, EHANGUP);
     208                        else
     209                                IPC_SET_RETVAL(call->data, ENOENT);
     210                }
     211
    201212                _ipc_answer_free_call(call);
    202                 return;
     213                return ENOENT;
    203214        }
    204215        _ipc_call(phone, box, call);
    205216       
    206217        spinlock_unlock(&phone->lock);
     218        return 0;
    207219}
    208220
     
    221233        box = phone->callee;
    222234        if (!box) {
     235                if (phone->busy == IPC_BUSY_CONNECTING) {
     236                        spinlock_unlock(&phone->lock);
     237                        return -1;
     238                }
     239                /* Already disconnected phone */
     240                phone->busy = IPC_BUSY_FREE;
    223241                spinlock_unlock(&phone->lock);
    224                 return -1;
     242                return 0;
    225243        }
    226244
     
    235253        _ipc_call(phone, box, call);
    236254
    237         phone->busy = 0;
     255        phone->busy = IPC_BUSY_FREE;
    238256
    239257        spinlock_unlock(&phone->lock);
     
    247265 * @param newbox Target answerbox
    248266 * @param oldbox Old answerbox
    249  */
    250 void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
     267 * @return 0 on forward ok, error code, if there was error
     268 *
     269 * - the return value serves only as an information for the forwarder,
     270 *   the original caller is notified automatically with EFORWARD
     271 */
     272int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
    251273{
    252274        spinlock_lock(&oldbox->lock);
    253         atomic_dec(&call->data.phone->active_calls);
    254275        list_remove(&call->list);
    255276        spinlock_unlock(&oldbox->lock);
    256277
    257         ipc_call(newphone, call);
     278        return ipc_call(newphone, call);
    258279}
    259280
     
    280301                request = list_get_instance(box->answers.next, call_t, list);
    281302                list_remove(&request->list);
    282                 printf("%d %P\n", IPC_GET_METHOD(request->data),
    283                        request->data.phone);
    284303                atomic_dec(&request->data.phone->active_calls);
    285304        } else if (!list_empty(&box->calls)) {
     
    314333void ipc_cleanup(task_t *task)
    315334{
    316         /* Cancel all calls in my dispatch queue */
     335        int i;
     336
     337        /* Disconnect all our phones ('ipc_phone_hangup') */
     338        for (i=0;i < IPC_MAX_PHONES; i++)
     339                ipc_phone_hangup(&task->phones[i]);
     340
     341        /* Disconnect all phones connected to answerbox */
     342
     343        /* Answer all messages in 'calls' and 'dispatched_calls' queues */
    317344       
    318 }
     345        /* Wait for all async answers to arrive */
     346}
  • generic/src/ipc/ipcrsc.c

    rb4b45210 r9f22213  
    7171 *   calls are answered, the phone is deallocated.
    7272 *
    73  * *** The answerbox hangs up (ipc_answer(ESLAM))
    74  * - The phone is disconnected. IPC_M_ANSWERBOX_HUNGUP notification
    75  *   is sent to source task, the calling process is expected to
     73 * *** The answerbox hangs up (ipc_answer(EHANGUP))
     74 * - The phone is disconnected. EHANGUP response code is sent
     75 *   to the calling process. All new calls through this phone
     76 *   get a EHUNGUP error code, the task is expected to
    7677 *   send an sys_ipc_hangup after cleaning up it's internal structures.
     78 *
     79 * Call forwarding
     80 *
     81 * The call can be forwarded, so that the answer to call is passed directly
     82 * to the original sender. However, this poses special problems regarding
     83 * routing of hangup messages.
     84 *
     85 * sys_ipc_hangup -> IPC_M_PHONE_HUNGUP
     86 * - this message CANNOT be forwarded
     87 *
     88 * EHANGUP during forward
     89 * - The *forwarding* phone will be closed, EFORWARD is sent to receiver.
     90 *
     91 * EHANGUP, ENOENT during forward
     92 * - EFORWARD is sent to the receiver, ipc_forward returns error code EFORWARD
    7793 *
    7894 * Cleanup strategy
    7995 *
    80  * 1) Disconnect all our phones ('sys_ipc_hangup')
     96 * 1) Disconnect all our phones ('ipc_phone_hangup').
    8197 *
    8298 * 2) Disconnect all phones connected to answerbox.
    83  *    * Send message 'PHONE_DISCONNECTED' to the target application
    84  * - Once all phones are disconnected, no further calls can arrive
    8599 *
    86100 * 3) Answer all messages in 'calls' and 'dispatched_calls' queues with
    87  *    appropriate error code.
     101 *    appropriate error code (EHANGUP, EFORWARD).
    88102 *
    89  * 4) Wait for all async answers to arrive
     103 * 4) Wait for all async answers to arrive.
    90104 *
    91105 */
     
    117131       
    118132        for (i=0; i < IPC_MAX_PHONES; i++) {
    119                 if (!TASK->phones[i].busy && !atomic_get(&TASK->phones[i].active_calls)) {
    120                         TASK->phones[i].busy = 1;
     133                if (TASK->phones[i].busy==IPC_BUSY_FREE && !atomic_get(&TASK->phones[i].active_calls)) {
     134                        TASK->phones[i].busy = IPC_BUSY_CONNECTING;
    121135                        break;
    122136                }
     
    137151        spinlock_lock(&TASK->lock);
    138152
    139         ASSERT(TASK->phones[phoneid].busy);
     153        ASSERT(TASK->phones[phoneid].busy == IPC_BUSY_CONNECTING);
    140154        ASSERT(! TASK->phones[phoneid].callee);
    141155
    142         TASK->phones[phoneid].busy = 0;
     156        TASK->phones[phoneid].busy = IPC_BUSY_FREE;
    143157        spinlock_unlock(&TASK->lock);
    144158}
     
    156170        phone_t *phone = &TASK->phones[phoneid];
    157171       
    158         ASSERT(phone->busy);
     172        ASSERT(phone->busy == IPC_BUSY_CONNECTING);
    159173        ipc_phone_connect(phone, box);
    160174}
  • generic/src/ipc/sysipc.c

    rb4b45210 r9f22213  
    7676
    7777/** Return true if the caller (ipc_answer) should save
    78  * the old call contents and call answer_preprocess
    79  */
    80 static inline int answer_will_preprocess(call_t *call)
     78 * the old call contents for answer_preprocess
     79 */
     80static inline int answer_need_old(call_t *call)
    8181{
    8282        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
     
    9191{
    9292        int phoneid;
     93
     94        if (IPC_GET_RETVAL(answer->data) == EHANGUP) {
     95                /* Atomic operation */
     96                answer->data.phone->callee = NULL;
     97        }
     98
     99        if (!olddata)
     100                return;
    93101
    94102        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
     
    98106                        phone_dealloc(phoneid);
    99107                } else {
    100                         /* The connection was accepted */
     108                                /* The connection was accepted */
    101109                        phone_connect(phoneid,&answer->sender->answerbox);
    102110                }
     
    118126static int process_answer(answerbox_t *box,call_t *call)
    119127{
     128        if (IPC_GET_RETVAL(call->data) == EHANGUP && \
     129            call->flags & IPC_CALL_FORWARDED)
     130                IPC_SET_RETVAL(call->data, EFORWARD);
    120131        return 0;
    121132}
     
    276287                return ENOENT;
    277288
     289        call->flags |= IPC_CALL_FORWARDED;
     290
    278291        GET_CHECK_PHONE(phone, phoneid, {
    279292                IPC_SET_RETVAL(call->data, EFORWARD);
     
    299312        }
    300313
    301         ipc_forward(call, phone, &TASK->answerbox);
    302 
    303         return 0;
     314        return ipc_forward(call, phone, &TASK->answerbox);
    304315}
    305316
     
    310321        call_t *call;
    311322        ipc_data_t saved_data;
    312         int preprocess = 0;
     323        int saveddata = 0;
    313324
    314325        call = get_call(callid);
     
    316327                return ENOENT;
    317328
    318         if (answer_will_preprocess(call)) {
     329        if (answer_need_old(call)) {
    319330                memcpy(&saved_data, &call->data, sizeof(call->data));
    320                 preprocess = 1;
     331                saveddata = 1;
    321332        }
    322333
     
    324335        IPC_SET_ARG1(call->data, arg1);
    325336        IPC_SET_ARG2(call->data, arg2);
    326 
    327         if (preprocess)
    328                 answer_preprocess(call, &saved_data);
     337        answer_preprocess(call, saveddata ? &saved_data : NULL);
    329338
    330339        ipc_answer(&TASK->answerbox, call);
     
    337346        call_t *call;
    338347        ipc_data_t saved_data;
    339         int preprocess = 0;
     348        int saveddata = 0;
    340349
    341350        call = get_call(callid);
     
    343352                return ENOENT;
    344353
    345         if (answer_will_preprocess(call)) {
     354        if (answer_need_old(call)) {
    346355                memcpy(&saved_data, &call->data, sizeof(call->data));
    347                 preprocess = 1;
     356                saveddata = 1;
    348357        }
    349358        copy_from_uspace(&call->data.args, &data->args,
    350359                         sizeof(call->data.args));
    351360
    352         if (preprocess)
    353                 answer_preprocess(call, &saved_data);
     361        answer_preprocess(call, saveddata ? &saved_data : NULL);
    354362       
    355363        ipc_answer(&TASK->answerbox, call);
     
    449457restart:       
    450458        call = ipc_wait_for_call(&TASK->answerbox, flags);
     459        if (!call)
     460                return 0;
    451461
    452462        if (call->flags & IPC_CALL_ANSWERED) {
Note: See TracChangeset for help on using the changeset viewer.