source: mainline/kernel/generic/src/ipc/ops/connclone.c@ b1e6269

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b1e6269 was b1e6269, checked in by Jakub Jermar <jakub@…>, 13 years ago

Add two new sysipc_ops_t members:

  • request_forget()
  • answer_cleanup()

Call these members to perform cleanup at appropriate times.

  • Property mode set to 100644
File size: 4.1 KB
RevLine 
[f0defd2]1/*
2 * Copyright (c) 2012 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup genericipc
30 * @{
31 */
32/** @file
33 */
34
35#include <ipc/sysipc_ops.h>
[e8039a86]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
[b1e6269]99static void answer_cleanup(call_t *answer, ipc_data_t *olddata)
100{
101 int phoneid = (int) IPC_GET_ARG1(*olddata);
102 phone_t *phone = &TASK->phones[phoneid];
103
104 /*
105 * In this case, the connection was established at the request
106 * time and therefore we need to slam the phone. We don't
107 * merely hangup as that would result in sending IPC_M_HUNGUP
108 * to the third party on the other side of the cloned phone.
109 */
110 mutex_lock(&phone->lock);
111 if (phone->state == IPC_PHONE_CONNECTED) {
112 irq_spinlock_lock(&phone->callee->lock, true);
113 list_remove(&phone->link);
114 phone->state = IPC_PHONE_SLAMMED;
115 irq_spinlock_unlock(&phone->callee->lock, true);
116 }
117 mutex_unlock(&phone->lock);
118}
119
[e8039a86]120static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
121{
122 if (IPC_GET_RETVAL(answer->data) != EOK) {
123 /*
124 * The recipient of the cloned phone rejected the offer.
125 */
[b1e6269]126 answer_cleanup(answer, olddata);
[e8039a86]127 }
128
129 return EOK;
130}
[f0defd2]131
132sysipc_ops_t ipc_m_connection_clone_ops = {
[e8039a86]133 .request_preprocess = request_preprocess,
[b1e6269]134 .request_forget = null_request_forget,
[f0defd2]135 .request_process = null_request_process,
[b1e6269]136 .answer_cleanup = answer_cleanup,
[e8039a86]137 .answer_preprocess = answer_preprocess,
[f0defd2]138 .answer_process = null_answer_process,
139};
140
141/** @}
142 */
Note: See TracBrowser for help on using the repository browser.