Changeset e8039a86 in mainline for kernel/generic/src/ipc/ops/connclone.c
- Timestamp:
- 2012-08-20T23:21:41Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0343a1b
- Parents:
- 642dc72
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ops/connclone.c
r642dc72 re8039a86 34 34 35 35 #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 42 static 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 54 static 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 61 static 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 99 static 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 } 36 126 37 127 sysipc_ops_t ipc_m_connection_clone_ops = { 38 .request_preprocess = null_request_preprocess,128 .request_preprocess = request_preprocess, 39 129 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,130 .answer_preprocess = answer_preprocess, 41 131 .answer_process = null_answer_process, 42 132 };
Note:
See TracChangeset
for help on using the changeset viewer.