Ignore:
Timestamp:
2012-08-20T23:21:41Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0343a1b
Parents:
642dc72
Message:

Separate system IPC logic into dedicated ops structure hooks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/ops/connclone.c

    r642dc72 re8039a86  
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <ipc/ipcrsc.h>
     38#include <synch/mutex.h>
     39#include <abi/errno.h>
     40#include <arch.h>
     41
     42static void phones_lock(phone_t *p1, phone_t *p2)
     43{
     44        if (p1 < p2) {
     45                mutex_lock(&p1->lock);
     46                mutex_lock(&p2->lock);
     47        } else if (p1 > p2) {
     48                mutex_lock(&p2->lock);
     49                mutex_lock(&p1->lock);
     50        } else
     51                mutex_lock(&p1->lock);
     52}
     53
     54static void phones_unlock(phone_t *p1, phone_t *p2)
     55{
     56        mutex_unlock(&p1->lock);
     57        if (p1 != p2)
     58                mutex_unlock(&p2->lock);
     59}
     60
     61static int request_preprocess(call_t *call, phone_t *phone)
     62{
     63        phone_t *cloned_phone;
     64
     65        if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
     66                return ENOENT;
     67               
     68        phones_lock(cloned_phone, phone);
     69               
     70        if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
     71            phone->state != IPC_PHONE_CONNECTED) {
     72                phones_unlock(cloned_phone, phone);
     73                return EINVAL;
     74        }
     75               
     76        /*
     77         * We can be pretty sure now that both tasks exist and we are
     78         * connected to them. As we continue to hold the phone locks,
     79         * we are effectively preventing them from finishing their
     80         * potential cleanup.
     81         *
     82         */
     83        int newphid = phone_alloc(phone->callee->task);
     84        if (newphid < 0) {
     85                phones_unlock(cloned_phone, phone);
     86                return ELIMIT;
     87        }
     88               
     89        ipc_phone_connect(&phone->callee->task->phones[newphid],
     90            cloned_phone->callee);
     91        phones_unlock(cloned_phone, phone);
     92               
     93        /* Set the new phone for the callee. */
     94        IPC_SET_ARG1(call->data, newphid);
     95
     96        return EOK;
     97}
     98
     99static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     100{
     101        if (IPC_GET_RETVAL(answer->data) != EOK) {
     102                /*
     103                 * The recipient of the cloned phone rejected the offer.
     104                 */
     105                int phoneid = (int) IPC_GET_ARG1(*olddata);
     106                phone_t *phone = &TASK->phones[phoneid];
     107
     108                /*
     109                 * In this case, the connection was established at the request
     110                 * time and therefore we need to slam the phone.  We don't
     111                 * merely hangup as that would result in sending IPC_M_HUNGUP
     112                 * to the third party on the other side of the cloned phone.
     113                 */
     114                mutex_lock(&phone->lock);
     115                if (phone->state == IPC_PHONE_CONNECTED) {
     116                        irq_spinlock_lock(&phone->callee->lock, true);
     117                        list_remove(&phone->link);
     118                        phone->state = IPC_PHONE_SLAMMED;
     119                        irq_spinlock_unlock(&phone->callee->lock, true);
     120                }
     121                mutex_unlock(&phone->lock);
     122        }
     123
     124        return EOK;
     125}
    36126
    37127sysipc_ops_t ipc_m_connection_clone_ops = {
    38         .request_preprocess = null_request_preprocess,
     128        .request_preprocess = request_preprocess,
    39129        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     130        .answer_preprocess = answer_preprocess,
    41131        .answer_process = null_answer_process,
    42132};
Note: See TracChangeset for help on using the changeset viewer.