2
* Copyright (c) 2012 Jakub Jermar
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
29
/** @addtogroup genericipc
35
#include <ipc/sysipc_ops.h>
37
#include <ipc/ipcrsc.h>
38
#include <synch/mutex.h>
39
#include <abi/errno.h>
42
static void phones_lock(phone_t *p1, phone_t *p2)
45
mutex_lock(&p1->lock);
46
mutex_lock(&p2->lock);
48
mutex_lock(&p2->lock);
49
mutex_lock(&p1->lock);
51
mutex_lock(&p1->lock);
54
static void phones_unlock(phone_t *p1, phone_t *p2)
56
mutex_unlock(&p1->lock);
58
mutex_unlock(&p2->lock);
61
static int request_preprocess(call_t *call, phone_t *phone)
63
phone_t *cloned_phone;
65
if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
68
phones_lock(cloned_phone, phone);
70
if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
71
phone->state != IPC_PHONE_CONNECTED) {
72
phones_unlock(cloned_phone, phone);
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
83
int newphid = phone_alloc(phone->callee->task);
85
phones_unlock(cloned_phone, phone);
89
(void) ipc_phone_connect(&phone->callee->task->phones[newphid],
90
cloned_phone->callee);
91
phones_unlock(cloned_phone, phone);
93
/* Set the new phone for the callee. */
94
IPC_SET_ARG1(call->data, newphid);
99
static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
101
int phoneid = (int) IPC_GET_ARG1(*olddata);
102
phone_t *phone = &TASK->phones[phoneid];
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.
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);
117
mutex_unlock(&phone->lock);
122
static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
124
if (IPC_GET_RETVAL(answer->data) != EOK) {
126
* The recipient of the cloned phone rejected the offer.
128
answer_cleanup(answer, olddata);
134
sysipc_ops_t ipc_m_connection_clone_ops = {
135
.request_preprocess = request_preprocess,
136
.request_forget = null_request_forget,
137
.request_process = null_request_process,
138
.answer_cleanup = answer_cleanup,
139
.answer_preprocess = answer_preprocess,
140
.answer_process = null_answer_process,