Changeset e8039a86 in mainline for kernel/generic/src/ipc/ops


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.

Location:
kernel/generic/src/ipc/ops
Files:
10 edited

Legend:

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

    r642dc72 re8039a86  
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <synch/mutex.h>
     38#include <abi/errno.h>
     39
     40static int request_preprocess(call_t *call, phone_t *phone)
     41{
     42        IPC_SET_ARG5(call->data, (sysarg_t) phone);
     43
     44        return EOK;     
     45}
     46
     47static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     48{
     49        phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
     50
     51        if (IPC_GET_RETVAL(answer->data) != EOK) {
     52                /*
     53                 * The other party on the cloned phone rejected our request
     54                 * for connection on the protocol level.  We need to break the
     55                 * connection without sending IPC_M_HUNGUP back.
     56                 */
     57                mutex_lock(&phone->lock);
     58                if (phone->state == IPC_PHONE_CONNECTED) {
     59                        irq_spinlock_lock(&phone->callee->lock, true);
     60                        list_remove(&phone->link);
     61                        phone->state = IPC_PHONE_SLAMMED;
     62                        irq_spinlock_unlock(&phone->callee->lock, true);
     63                }
     64                mutex_unlock(&phone->lock);
     65        }
     66       
     67        return EOK;
     68}
    3669
    3770sysipc_ops_t ipc_m_clone_establish_ops = {
    38         .request_preprocess = null_request_preprocess,
     71        .request_preprocess = request_preprocess,
    3972        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     73        .answer_preprocess = answer_preprocess,
    4174        .answer_process = null_answer_process,
    4275};
  • kernel/generic/src/ipc/ops/conctmeto.c

    r642dc72 re8039a86  
    11/*
     2 * Copyright (c) 2006 Ondrej Palkovsky
    23 * Copyright (c) 2012 Jakub Jermar
    34 * All rights reserved.
     
    3435
    3536#include <ipc/sysipc_ops.h>
     37#include <ipc/ipc.h>
     38#include <ipc/ipcrsc.h>
     39#include <abi/errno.h>
     40#include <arch.h>
    3641
    37 static sysipc_ops_t ipc_m_connect_me_to_ops = {
    38         .request_preprocess = null_request_preprocess,
     42static int request_preprocess(call_t *call, phone_t *phone)
     43{
     44        int newphid = phone_alloc(TASK);
     45
     46        if (newphid < 0)
     47                return ELIMIT;
     48               
     49        /* Set arg5 for server */
     50        IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
     51        call->flags |= IPC_CALL_CONN_ME_TO;
     52        call->priv = newphid;
     53
     54        return EOK;
     55}
     56
     57static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     58{
     59        phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
     60
     61        /* If the user accepted call, connect */
     62        if (IPC_GET_RETVAL(answer->data) == EOK)
     63                ipc_phone_connect(phone, &TASK->answerbox);
     64
     65        return EOK;
     66}
     67
     68
     69sysipc_ops_t ipc_m_connect_me_to_ops = {
     70        .request_preprocess = request_preprocess,
    3971        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     72        .answer_preprocess = answer_preprocess,
    4173        .answer_process = null_answer_process,
    4274};
    4375
    44 sysipc_ops_t *ipc_m_connect_me_to_ops_p = &ipc_m_connect_me_to_ops;
    45 
    4676/** @}
    4777 */
  • kernel/generic/src/ipc/ops/concttome.c

    r642dc72 re8039a86  
    11/*
     2 * Copyright (c) 2006 Ondrej Palkovsky
    23 * Copyright (c) 2012 Jakub Jermar
    34 * All rights reserved.
     
    3435
    3536#include <ipc/sysipc_ops.h>
     37#include <ipc/ipc.h>
     38#include <ipc/ipcrsc.h>
     39#include <abi/errno.h>
     40#include <arch.h>
     41
     42static int request_process(call_t *call, answerbox_t *box)
     43{
     44        int phoneid = phone_alloc(TASK);
     45
     46        if (phoneid < 0) {  /* Failed to allocate phone */
     47                IPC_SET_RETVAL(call->data, ELIMIT);
     48                ipc_answer(box, call);
     49                return -1;
     50        }
     51               
     52        IPC_SET_ARG5(call->data, phoneid);
     53       
     54        return EOK;
     55}
     56
     57static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     58{
     59        int phoneid = (int) IPC_GET_ARG5(*olddata);
     60
     61        if (IPC_GET_RETVAL(answer->data) != EOK) {
     62                /* The connection was not accepted */
     63                int phoneid = (int) IPC_GET_ARG5(*olddata);
     64       
     65                phone_dealloc(phoneid);
     66        } else {
     67                /* The connection was accepted */
     68                phone_connect(phoneid, &answer->sender->answerbox);
     69                /* Set 'phone hash' as arg5 of response */
     70                IPC_SET_ARG5(answer->data, (sysarg_t) &TASK->phones[phoneid]);
     71        }
     72
     73        return EOK;
     74}
     75
    3676
    3777sysipc_ops_t ipc_m_connect_to_me_ops = {
    3878        .request_preprocess = null_request_preprocess,
    39         .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     79        .request_process = request_process,
     80        .answer_preprocess = answer_preprocess,
    4181        .answer_process = null_answer_process,
    4282};
  • 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};
  • kernel/generic/src/ipc/ops/dataread.c

    r642dc72 re8039a86  
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <mm/slab.h>
     38#include <abi/errno.h>
     39#include <syscall/copy.h>
     40#include <config.h>
     41
     42static int request_preprocess(call_t *call, phone_t *phone)
     43{
     44        size_t size = IPC_GET_ARG2(call->data);
     45
     46        if (size > DATA_XFER_LIMIT) {
     47                int flags = IPC_GET_ARG3(call->data);
     48
     49                if (flags & IPC_XF_RESTRICT)
     50                        IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
     51                else
     52                        return ELIMIT;
     53        }
     54
     55        return EOK;
     56}
     57
     58static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     59{
     60        ASSERT(!answer->buffer);
     61
     62        if (!IPC_GET_RETVAL(answer->data)) {
     63                /* The recipient agreed to send data. */
     64                uintptr_t src = IPC_GET_ARG1(answer->data);
     65                uintptr_t dst = IPC_GET_ARG1(*olddata);
     66                size_t max_size = IPC_GET_ARG2(*olddata);
     67                size_t size = IPC_GET_ARG2(answer->data);
     68                if (size && size <= max_size) {
     69                        /*
     70                         * Copy the destination VA so that this piece of
     71                         * information is not lost.
     72                         */
     73                        IPC_SET_ARG1(answer->data, dst);
     74                               
     75                        answer->buffer = malloc(size, 0);
     76                        int rc = copy_from_uspace(answer->buffer,
     77                            (void *) src, size);
     78                        if (rc) {
     79                                IPC_SET_RETVAL(answer->data, rc);
     80                                free(answer->buffer);
     81                                answer->buffer = NULL;
     82                        }
     83                } else if (!size) {
     84                        IPC_SET_RETVAL(answer->data, EOK);
     85                } else {
     86                        IPC_SET_RETVAL(answer->data, ELIMIT);
     87                }
     88        }
     89
     90        return EOK;
     91}
    3692
    3793sysipc_ops_t ipc_m_data_read_ops = {
    38         .request_preprocess = null_request_preprocess,
     94        .request_preprocess = request_preprocess,
    3995        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     96        .answer_preprocess = answer_preprocess,
    4197        .answer_process = null_answer_process,
    4298};
  • kernel/generic/src/ipc/ops/datawrite.c

    r642dc72 re8039a86  
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <mm/slab.h>
     38#include <abi/errno.h>
     39#include <syscall/copy.h>
     40#include <config.h>
     41
     42static int request_preprocess(call_t *call, phone_t *phone)
     43{
     44        uintptr_t src = IPC_GET_ARG1(call->data);
     45        size_t size = IPC_GET_ARG2(call->data);
     46
     47        if (size > DATA_XFER_LIMIT) {
     48                int flags = IPC_GET_ARG3(call->data);
     49
     50                if (flags & IPC_XF_RESTRICT) {
     51                        size = DATA_XFER_LIMIT;
     52                        IPC_SET_ARG2(call->data, size);
     53                } else
     54                        return ELIMIT;
     55        }
     56
     57        call->buffer = (uint8_t *) malloc(size, 0);
     58        int rc = copy_from_uspace(call->buffer, (void *) src, size);
     59        if (rc != 0) {
     60                free(call->buffer);
     61                return rc;
     62        }
     63               
     64        return EOK;
     65}
     66
     67static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     68{
     69        ASSERT(answer->buffer);
     70
     71        if (!IPC_GET_RETVAL(answer->data)) {
     72                /* The recipient agreed to receive data. */
     73                uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data);
     74                size_t size = (size_t)IPC_GET_ARG2(answer->data);
     75                size_t max_size = (size_t)IPC_GET_ARG2(*olddata);
     76                       
     77                if (size <= max_size) {
     78                        int rc = copy_to_uspace((void *) dst,
     79                            answer->buffer, size);
     80                        if (rc)
     81                                IPC_SET_RETVAL(answer->data, rc);
     82                } else {
     83                        IPC_SET_RETVAL(answer->data, ELIMIT);
     84                }
     85        }
     86        free(answer->buffer);
     87        answer->buffer = NULL;
     88
     89        return EOK;
     90}
     91
    3692
    3793sysipc_ops_t ipc_m_data_write_ops = {
    38         .request_preprocess = null_request_preprocess,
     94        .request_preprocess = request_preprocess,
    3995        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     96        .answer_preprocess = answer_preprocess,
    4197        .answer_process = null_answer_process,
    4298};
  • kernel/generic/src/ipc/ops/debug.c

    r642dc72 re8039a86  
    11/*
    2  * Copyright (c) 2012 Jakub Jermar
     2 * Copyright (c) 2008 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <udebug/udebug_ipc.h>
     38
     39static int request_process(call_t *call, answerbox_t *box)
     40{
     41        return -1;
     42}
    3643
    3744sysipc_ops_t ipc_m_debug_ops = {
     45#ifdef CONFIG_UDEBUG
     46        .request_preprocess = udebug_request_preprocess,
     47#else
    3848        .request_preprocess = null_request_preprocess,
    39         .request_process = null_request_process,
     49#endif
     50        .request_process = request_process,
    4051        .answer_preprocess = null_answer_preprocess,
    4152        .answer_process = null_answer_process,
  • kernel/generic/src/ipc/ops/sharein.c

    r642dc72 re8039a86  
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <mm/as.h>
     38#include <synch/spinlock.h>
     39#include <proc/task.h>
     40#include <abi/errno.h>
     41#include <arch.h>
     42
     43static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     44{
     45        if (!IPC_GET_RETVAL(answer->data)) {
     46                irq_spinlock_lock(&answer->sender->lock, true);
     47                as_t *as = answer->sender->as;
     48                irq_spinlock_unlock(&answer->sender->lock, true);
     49                       
     50                uintptr_t dst_base = (uintptr_t) -1;
     51                int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     52                    IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data),
     53                    &dst_base, IPC_GET_ARG3(answer->data));
     54                IPC_SET_ARG4(answer->data, dst_base);
     55                IPC_SET_RETVAL(answer->data, rc);
     56        }
     57       
     58        return EOK;
     59}
    3660
    3761sysipc_ops_t ipc_m_share_in_ops = {
    3862        .request_preprocess = null_request_preprocess,
    3963        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     64        .answer_preprocess = answer_preprocess,
    4165        .answer_process = null_answer_process,
    4266};
  • kernel/generic/src/ipc/ops/shareout.c

    r642dc72 re8039a86  
    3434
    3535#include <ipc/sysipc_ops.h>
     36#include <ipc/ipc.h>
     37#include <mm/as.h>
     38#include <synch/spinlock.h>
     39#include <proc/task.h>
     40#include <syscall/copy.h>
     41#include <abi/errno.h>
     42#include <arch.h>
     43
     44static int request_preprocess(call_t *call, phone_t *phone)
     45{
     46        size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
     47
     48        if (!size)
     49                return EPERM;
     50        IPC_SET_ARG2(call->data, size);
     51
     52        return EOK;
     53}
     54
     55static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     56{
     57        int rc = EOK;
     58
     59        if (!IPC_GET_RETVAL(answer->data)) {
     60                /* Accepted, handle as_area receipt */
     61
     62                irq_spinlock_lock(&answer->sender->lock, true);
     63                as_t *as = answer->sender->as;
     64                irq_spinlock_unlock(&answer->sender->lock, true);
     65
     66                uintptr_t dst_base = (uintptr_t) -1;
     67                rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     68                    IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata),
     69                    &dst_base, IPC_GET_ARG1(answer->data));
     70                       
     71                if (rc == EOK) {
     72                        rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data),
     73                            &dst_base, sizeof(dst_base));
     74                }
     75                       
     76                IPC_SET_RETVAL(answer->data, rc);
     77        }
     78
     79        return rc;
     80}
    3681
    3782sysipc_ops_t ipc_m_share_out_ops = {
    38         .request_preprocess = null_request_preprocess,
     83        .request_preprocess = request_preprocess,
    3984        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     85        .answer_preprocess = answer_preprocess,
    4186        .answer_process = null_answer_process,
    4287};
  • kernel/generic/src/ipc/ops/stchngath.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 <proc/task.h>
     40#include <abi/errno.h>
     41#include <macros.h>
     42
     43static int request_preprocess(call_t *call, phone_t *phone)
     44{
     45        phone_t *sender_phone;
     46        task_t *other_task_s;
     47
     48        if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
     49                return ENOENT;
     50
     51        mutex_lock(&sender_phone->lock);
     52        if (sender_phone->state != IPC_PHONE_CONNECTED) {
     53                mutex_unlock(&sender_phone->lock);
     54                return EINVAL;
     55        }
     56
     57        other_task_s = sender_phone->callee->task;
     58
     59        mutex_unlock(&sender_phone->lock);
     60
     61        /* Remember the third party task hash. */
     62        IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
     63
     64        return EOK;
     65}
     66
     67static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     68{
     69        int rc = EOK;
     70
     71        if (!IPC_GET_RETVAL(answer->data)) {
     72                /* The recipient authorized the change of state. */
     73                phone_t *recipient_phone;
     74                task_t *other_task_s;
     75                task_t *other_task_r;
     76
     77                rc = phone_get(IPC_GET_ARG1(answer->data),
     78                    &recipient_phone);
     79                if (rc != EOK) {
     80                        IPC_SET_RETVAL(answer->data, ENOENT);
     81                        return ENOENT;
     82                }
     83
     84                mutex_lock(&recipient_phone->lock);
     85                if (recipient_phone->state != IPC_PHONE_CONNECTED) {
     86                        mutex_unlock(&recipient_phone->lock);
     87                        IPC_SET_RETVAL(answer->data, EINVAL);
     88                        return EINVAL;
     89                }
     90
     91                other_task_r = recipient_phone->callee->task;
     92                other_task_s = (task_t *) IPC_GET_ARG5(*olddata);
     93
     94                /*
     95                 * See if both the sender and the recipient meant the
     96                 * same third party task.
     97                 */
     98                if (other_task_r != other_task_s) {
     99                        IPC_SET_RETVAL(answer->data, EINVAL);
     100                        rc = EINVAL;
     101                } else {
     102                        rc = event_task_notify_5(other_task_r,
     103                            EVENT_TASK_STATE_CHANGE, false,
     104                            IPC_GET_ARG1(*olddata),
     105                            IPC_GET_ARG2(*olddata),
     106                            IPC_GET_ARG3(*olddata),
     107                            LOWER32(olddata->task_id),
     108                            UPPER32(olddata->task_id));
     109                        IPC_SET_RETVAL(answer->data, rc);
     110                }
     111
     112                mutex_unlock(&recipient_phone->lock);
     113        }
     114
     115        return rc;
     116}
    36117
    37118sysipc_ops_t ipc_m_state_change_authorize_ops = {
    38         .request_preprocess = null_request_preprocess,
     119        .request_preprocess = request_preprocess,
    39120        .request_process = null_request_process,
    40         .answer_preprocess = null_answer_preprocess,
     121        .answer_preprocess = answer_preprocess,
    41122        .answer_process = null_answer_process,
    42123};
Note: See TracChangeset for help on using the changeset viewer.