source: mainline/kernel/generic/src/ipc/ipcrsc.c@ a35b458

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[4e49572]1/*
[df4ed85]2 * Copyright (c) 2006 Ondrej Palkovsky
[4e49572]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
[cc73a8a1]29/** @addtogroup genericipc
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[4e49572]35/* IPC resources management
36 *
[51ec40f]37 * The goal of this source code is to properly manage IPC resources and allow
38 * straight and clean clean-up procedure upon task termination.
[4e49572]39 *
40 * The pattern of usage of the resources is:
[30c27e9]41 * - allocate empty phone capability slot, connect | deallocate slot
[4e49572]42 * - disconnect connected phone (some messages might be on the fly)
43 * - find phone in slot and send a message using phone
44 * - answer message to phone
[fbcfd458]45 * - hangup phone (the caller has hung up)
46 * - hangup phone (the answerbox is exiting)
[da1bafb]47 *
[ba81cab]48 * Locking strategy
49 *
[51ec40f]50 * - To use a phone, disconnect a phone etc., the phone must be first locked and
51 * then checked that it is connected
52 * - To connect an allocated phone it need not be locked (assigning pointer is
53 * atomic on all platforms)
[ba81cab]54 *
[30c27e9]55 * - To find an empty phone capability slot, the TASK must be locked
[ba81cab]56 * - To answer a message, the answerbox must be locked
57 * - The locking of phone and answerbox is done at the ipc_ level.
[51ec40f]58 * It is perfectly correct to pass unconnected phone to these functions and
59 * proper reply will be generated.
[ba81cab]60 *
61 * Locking order
62 *
63 * - first phone, then answerbox
64 * + Easy locking on calls
[51ec40f]65 * - Very hard traversing list of phones when disconnecting because the phones
66 * may disconnect during traversal of list of connected phones. The only
67 * possibility is try_lock with restart of list traversal.
[ba81cab]68 *
[fbcfd458]69 * Destroying is less frequent, this approach is taken.
70 *
[7c7aae16]71 * Phone call
72 *
73 * *** Connect_me_to ***
[51ec40f]74 * The caller sends IPC_M_CONNECT_ME_TO to an answerbox. The server receives
[38c706cc]75 * 'phoneid' of the connecting phone as an ARG5. If it answers with RETVAL=0,
[51ec40f]76 * the phonecall is accepted, otherwise it is refused.
[7c7aae16]77 *
78 * *** Connect_to_me ***
[30c27e9]79 * The caller sends IPC_M_CONNECT_TO_ME.
[51ec40f]80 * The server receives an automatically opened phoneid. If it accepts
[30c27e9]81 * (RETVAL=0), it can use the phoneid immediately. Possible race condition can
82 * arise, when the client receives messages from new connection before getting
83 * response for connect_to_me message. Userspace should implement handshake
84 * protocol that would control it.
[7c7aae16]85 *
[fbcfd458]86 * Phone hangup
[da1bafb]87 *
[fbcfd458]88 * *** The caller hangs up (sys_ipc_hangup) ***
89 * - The phone is disconnected (no more messages can be sent over this phone),
[51ec40f]90 * all in-progress messages are correctly handled. The answerbox receives
[30c27e9]91 * IPC_M_PHONE_HUNGUP call from the phone that hung up. When all async calls
92 * are answered, the phone is deallocated.
[ba81cab]93 *
[9f22213]94 * *** The answerbox hangs up (ipc_answer(EHANGUP))
[30c27e9]95 * - The phone is disconnected. EHANGUP response code is sent to the calling
96 * task. All new calls through this phone get a EHUNGUP error code, the task
97 * is expected to send an sys_ipc_hangup after cleaning up its internal
98 * structures.
99 *
[ba81cab]100 *
[9f22213]101 * Call forwarding
[da1bafb]102 *
[30c27e9]103 * The call can be forwarded, so that the answer to call is passed directly to
104 * the original sender. However, this poses special problems regarding routing
105 * of hangup messages.
[9f22213]106 *
107 * sys_ipc_hangup -> IPC_M_PHONE_HUNGUP
108 * - this message CANNOT be forwarded
109 *
110 * EHANGUP during forward
111 * - The *forwarding* phone will be closed, EFORWARD is sent to receiver.
112 *
113 * EHANGUP, ENOENT during forward
114 * - EFORWARD is sent to the receiver, ipc_forward returns error code EFORWARD
115 *
[ba81cab]116 * Cleanup strategy
[da1bafb]117 *
[9f22213]118 * 1) Disconnect all our phones ('ipc_phone_hangup').
[fbcfd458]119 *
120 * 2) Disconnect all phones connected to answerbox.
[ba81cab]121 *
[fbcfd458]122 * 3) Answer all messages in 'calls' and 'dispatched_calls' queues with
[9f22213]123 * appropriate error code (EHANGUP, EFORWARD).
[ba81cab]124 *
[7c7aae16]125 * 4) Wait for all async answers to arrive and dispose of them.
[da1bafb]126 *
[4e49572]127 */
128
129#include <synch/spinlock.h>
130#include <ipc/ipc.h>
131#include <arch.h>
132#include <proc/task.h>
133#include <ipc/ipcrsc.h>
[63e27ef]134#include <assert.h>
[e8039a86]135#include <abi/errno.h>
[3f74275]136#include <cap/cap.h>
[63d8f43]137#include <mm/slab.h>
[4e49572]138
[48bcf49]139static bool phone_reclaim(kobject_t *kobj)
[e8039a86]140{
[48bcf49]141 bool gc = false;
[9e87562]142
[48bcf49]143 mutex_lock(&kobj->phone->lock);
144 if (kobj->phone->state == IPC_PHONE_HUNGUP &&
145 atomic_get(&kobj->phone->active_calls) == 0)
146 gc = true;
147 mutex_unlock(&kobj->phone->lock);
[e8039a86]148
[48bcf49]149 return gc;
[05ffb41]150}
[239acce]151
[48bcf49]152static void phone_destroy(void *arg)
[05ffb41]153{
[48bcf49]154 phone_t *phone = (phone_t *) arg;
[82d515e9]155 slab_free(phone_cache, phone);
[48bcf49]156}
[05ffb41]157
[48bcf49]158static kobject_ops_t phone_kobject_ops = {
159 .reclaim = phone_reclaim,
160 .destroy = phone_destroy
161};
[63d8f43]162
[4e49572]163
[05ffb41]164/** Allocate new phone in the specified task.
[8b243f2]165 *
[05ffb41]166 * @param task Task for which to allocate a new phone.
[da1bafb]167 *
[09d01f2]168 * @param[out] out_handle New phone capability handle.
169 *
[cde999a]170 * @return An error code if a new capability cannot be allocated.
[8b243f2]171 */
[b7fd2a0]172errno_t phone_alloc(task_t *task, cap_handle_t *out_handle)
[7c7aae16]173{
[09d01f2]174 cap_handle_t handle;
[b7fd2a0]175 errno_t rc = cap_alloc(task, &handle);
[09d01f2]176 if (rc == EOK) {
[82d515e9]177 phone_t *phone = slab_alloc(phone_cache, FRAME_ATOMIC);
[63d8f43]178 if (!phone) {
179 cap_free(TASK, handle);
180 return ENOMEM;
181 }
[48bcf49]182 kobject_t *kobject = malloc(sizeof(kobject_t), FRAME_ATOMIC);
183 if (!kobject) {
184 cap_free(TASK, handle);
[82d515e9]185 slab_free(phone_cache, phone);
[48bcf49]186 return ENOMEM;
187 }
188
[63d8f43]189 ipc_phone_init(phone, task);
190 phone->state = IPC_PHONE_CONNECTING;
[9e87562]191
[48bcf49]192 kobject_initialize(kobject, KOBJECT_TYPE_PHONE, phone,
193 &phone_kobject_ops);
194 phone->kobject = kobject;
[a35b458]195
[48bcf49]196 cap_publish(task, handle, kobject);
[09d01f2]197
198 *out_handle = handle;
[05ffb41]199 }
[09d01f2]200 return rc;
[7c7aae16]201}
202
[8b243f2]203/** Free slot from a disconnected phone.
204 *
205 * All already sent messages will be correctly processed.
[fbcfd458]206 *
[3f74275]207 * @param handle Phone capability handle of the phone to be freed.
[da1bafb]208 *
[fbcfd458]209 */
[48bcf49]210void phone_dealloc(cap_handle_t handle)
[4e49572]211{
[48bcf49]212 kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_PHONE);
213 if (!kobj)
214 return;
[a35b458]215
[48bcf49]216 assert(kobj->phone);
217 assert(kobj->phone->state == IPC_PHONE_CONNECTING);
[a35b458]218
[48bcf49]219 kobject_put(kobj);
[3f74275]220 cap_free(TASK, handle);
[4e49572]221}
222
[8b243f2]223/** Connect phone to a given answerbox.
[ba81cab]224 *
[3f74275]225 * @param handle Capability handle of the phone to be connected.
226 * @param box Answerbox to which to connect the phone.
227 * @return True if the phone was connected, false otherwise.
[ba81cab]228 */
[48bcf49]229bool phone_connect(cap_handle_t handle, answerbox_t *box)
[4e49572]230{
[48bcf49]231 kobject_t *phone_obj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
232 if (!phone_obj)
233 return false;
[a35b458]234
[48bcf49]235 assert(phone_obj->phone->state == IPC_PHONE_CONNECTING);
[a35b458]236
[48bcf49]237 /* Hand over phone_obj reference to the answerbox */
238 return ipc_phone_connect(phone_obj->phone, box);
[4e49572]239}
[b45c443]240
[cc73a8a1]241/** @}
[b45c443]242 */
Note: See TracBrowser for help on using the repository browser.