source: mainline/uspace/lib/c/generic/async/ports.c@ 4805495

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

Make sure libc and abi header guards are reserved identifiers

It's only needed for a small subset that end up included from standard
headers, but for consistency this changes all of them.

  • Property mode set to 100644
File size: 7.3 KB
RevLine 
[49a796f1]1/*
2 * Copyright (c) 2006 Ondrej Palkovsky
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
[4805495]29#define _LIBC_ASYNC_C_
[49a796f1]30#include <ipc/ipc.h>
31#include <async.h>
32#include "../private/async.h"
[4805495]33#undef _LIBC_ASYNC_C_
[49a796f1]34
35#include <ipc/irq.h>
36#include <ipc/event.h>
37#include <fibril.h>
38#include <adt/hash_table.h>
39#include <adt/hash.h>
40#include <adt/list.h>
41#include <assert.h>
42#include <errno.h>
[bd41ac52]43#include <time.h>
[05882233]44#include <barrier.h>
[49a796f1]45#include <stdbool.h>
46#include <stdlib.h>
47#include <mem.h>
48#include <stdlib.h>
49#include <macros.h>
50#include <as.h>
51#include <abi/mm/as.h>
52#include "../private/libc.h"
[f787c8e]53#include "../private/fibril.h"
[49a796f1]54
55/** Interface data */
56typedef struct {
57 ht_link_t link;
58
59 /** Interface ID */
60 iface_t iface;
61
62 /** Interface ports */
63 hash_table_t port_hash_table;
64
65 /** Next available port ID */
66 port_id_t port_id_avail;
67} interface_t;
68
69/* Port data */
70typedef struct {
71 ht_link_t link;
72
73 /** Port ID */
74 port_id_t id;
75
76 /** Port connection handler */
77 async_port_handler_t handler;
78
79 /** Client data */
80 void *data;
81} port_t;
82
83/** Default fallback fibril function.
84 *
85 * This fallback fibril function gets called on incomming connections that do
86 * not have a specific handler defined.
87 *
[984a9ba]88 * @param call Data of the incoming call.
89 * @param arg Local argument
[49a796f1]90 *
91 */
[984a9ba]92static void default_fallback_port_handler(ipc_call_t *call, void *arg)
[49a796f1]93{
[984a9ba]94 async_answer_0(call, ENOENT);
[49a796f1]95}
96
97static async_port_handler_t fallback_port_handler =
98 default_fallback_port_handler;
99static void *fallback_port_data = NULL;
100
[5c76cc61]101/** Futex guarding the interface hash table. */
[45c8eea]102static fibril_rmutex_t interface_mutex;
[49a796f1]103static hash_table_t interface_hash_table;
104
105static size_t interface_key_hash(void *key)
106{
107 iface_t iface = *(iface_t *) key;
108 return iface;
109}
110
111static size_t interface_hash(const ht_link_t *item)
112{
113 interface_t *interface = hash_table_get_inst(item, interface_t, link);
114 return interface_key_hash(&interface->iface);
115}
116
117static bool interface_key_equal(void *key, const ht_link_t *item)
118{
119 iface_t iface = *(iface_t *) key;
120 interface_t *interface = hash_table_get_inst(item, interface_t, link);
121 return iface == interface->iface;
122}
123
124/** Operations for the port hash table. */
125static hash_table_ops_t interface_hash_table_ops = {
126 .hash = interface_hash,
127 .key_hash = interface_key_hash,
128 .key_equal = interface_key_equal,
129 .equal = NULL,
130 .remove_callback = NULL
131};
132
133static size_t port_key_hash(void *key)
134{
135 port_id_t port_id = *(port_id_t *) key;
136 return port_id;
137}
138
139static size_t port_hash(const ht_link_t *item)
140{
141 port_t *port = hash_table_get_inst(item, port_t, link);
142 return port_key_hash(&port->id);
143}
144
145static bool port_key_equal(void *key, const ht_link_t *item)
146{
147 port_id_t port_id = *(port_id_t *) key;
148 port_t *port = hash_table_get_inst(item, port_t, link);
149 return port_id == port->id;
150}
151
152/** Operations for the port hash table. */
153static hash_table_ops_t port_hash_table_ops = {
154 .hash = port_hash,
155 .key_hash = port_key_hash,
156 .key_equal = port_key_equal,
157 .equal = NULL,
158 .remove_callback = NULL
159};
160
161static interface_t *async_new_interface(iface_t iface)
162{
163 interface_t *interface =
164 (interface_t *) malloc(sizeof(interface_t));
165 if (!interface)
166 return NULL;
167
168 bool ret = hash_table_create(&interface->port_hash_table, 0, 0,
169 &port_hash_table_ops);
170 if (!ret) {
171 free(interface);
172 return NULL;
173 }
174
175 interface->iface = iface;
176 interface->port_id_avail = 0;
177
178 hash_table_insert(&interface_hash_table, &interface->link);
179
180 return interface;
181}
182
183static port_t *async_new_port(interface_t *interface,
184 async_port_handler_t handler, void *data)
185{
[5c76cc61]186 // TODO: Move the malloc out of critical section.
[49a796f1]187 port_t *port = (port_t *) malloc(sizeof(port_t));
188 if (!port)
189 return NULL;
190
191 port_id_t id = interface->port_id_avail;
192 interface->port_id_avail++;
193
194 port->id = id;
195 port->handler = handler;
196 port->data = data;
197
198 hash_table_insert(&interface->port_hash_table, &port->link);
199
200 return port;
201}
202
203errno_t async_create_port_internal(iface_t iface, async_port_handler_t handler,
204 void *data, port_id_t *port_id)
205{
206 interface_t *interface;
207
[9bde0d5]208 fibril_rmutex_lock(&interface_mutex);
[49a796f1]209
210 ht_link_t *link = hash_table_find(&interface_hash_table, &iface);
211 if (link)
212 interface = hash_table_get_inst(link, interface_t, link);
213 else
214 interface = async_new_interface(iface);
215
216 if (!interface) {
[9bde0d5]217 fibril_rmutex_unlock(&interface_mutex);
[49a796f1]218 return ENOMEM;
219 }
220
221 port_t *port = async_new_port(interface, handler, data);
222 if (!port) {
[9bde0d5]223 fibril_rmutex_unlock(&interface_mutex);
[49a796f1]224 return ENOMEM;
225 }
226
227 *port_id = port->id;
228
[9bde0d5]229 fibril_rmutex_unlock(&interface_mutex);
[49a796f1]230
231 return EOK;
232}
233
234errno_t async_create_port(iface_t iface, async_port_handler_t handler,
235 void *data, port_id_t *port_id)
236{
237 if ((iface & IFACE_MOD_MASK) == IFACE_MOD_CALLBACK)
238 return EINVAL;
239
240 return async_create_port_internal(iface, handler, data, port_id);
241}
242
243void async_set_fallback_port_handler(async_port_handler_t handler, void *data)
244{
245 assert(handler != NULL);
246
247 fallback_port_handler = handler;
248 fallback_port_data = data;
249}
250
251static port_t *async_find_port(iface_t iface, port_id_t port_id)
252{
253 port_t *port = NULL;
254
[9bde0d5]255 fibril_rmutex_lock(&interface_mutex);
[49a796f1]256
257 ht_link_t *link = hash_table_find(&interface_hash_table, &iface);
258 if (link) {
259 interface_t *interface =
260 hash_table_get_inst(link, interface_t, link);
261
262 link = hash_table_find(&interface->port_hash_table, &port_id);
263 if (link)
264 port = hash_table_get_inst(link, port_t, link);
265 }
266
[9bde0d5]267 fibril_rmutex_unlock(&interface_mutex);
[49a796f1]268
269 return port;
270}
271
272async_port_handler_t async_get_port_handler(iface_t iface, port_id_t port_id,
273 void **data)
274{
275 assert(data);
276
277 async_port_handler_t handler = fallback_port_handler;
278 *data = fallback_port_data;
279
280 port_t *port = async_find_port(iface, port_id);
281 if (port) {
282 handler = port->handler;
283 *data = port->data;
284 }
285
286 return handler;
287}
288
289/** Initialize the async framework.
290 *
291 */
292void __async_ports_init(void)
293{
[45c8eea]294 if (fibril_rmutex_initialize(&interface_mutex) != EOK)
295 abort();
296
[49a796f1]297 if (!hash_table_create(&interface_hash_table, 0, 0,
298 &interface_hash_table_ops))
299 abort();
300}
[25f6bddb]301
302void __async_ports_fini(void)
303{
304 fibril_rmutex_destroy(&interface_mutex);
305}
Note: See TracBrowser for help on using the repository browser.