source: mainline/uspace/app/trace/ipcp.c@ 2c4e1cc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2c4e1cc was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 8.8 KB
RevLine 
[9a1b20c]1/*
2 * Copyright (c) 2008 Jiri Svoboda
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 trace
30 * @{
31 */
32/** @file
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
[c1694b6b]37#include <str_error.h>
[7354b5e]38#include <inttypes.h>
[d9c8c81]39#include <adt/hash_table.h>
[c0699467]40#include <abi/ipc/methods.h>
[062d900]41#include <macros.h>
[9a1b20c]42#include "ipc_desc.h"
43#include "proto.h"
[1643855]44#include "trace.h"
[9a1b20c]45#include "ipcp.h"
46
47typedef struct {
[eadaeae8]48 cap_phone_handle_t phone_handle;
[9a1b20c]49 ipc_call_t question;
[abf3564]50 oper_t *oper;
[9a1b20c]51
[eadaeae8]52 cap_call_handle_t call_handle;
[9a1b20c]53
[062d900]54 ht_link_t link;
[9a1b20c]55} pending_call_t;
56
57typedef struct {
58 int server;
59 proto_t *proto;
60} connection_t;
61
62#define MAX_PHONE 64
63connection_t connections[MAX_PHONE];
64int have_conn[MAX_PHONE];
65
[062d900]66static hash_table_t pending_calls;
[9a1b20c]67
[8c125ad]68/*
69 * Pseudo-protocols
70 */
71proto_t *proto_system; /**< Protocol describing system IPC methods. */
72proto_t *proto_unknown; /**< Protocol with no known methods. */
73
[9a1b20c]74
[062d900]75static size_t pending_call_key_hash(void *key)
[9a1b20c]76{
[eadaeae8]77 cap_call_handle_t *chandle = (cap_call_handle_t *) key;
78 return CAP_HANDLE_RAW(*chandle);
[9a1b20c]79}
80
[062d900]81static size_t pending_call_hash(const ht_link_t *item)
[9a1b20c]82{
[062d900]83 pending_call_t *hs = hash_table_get_inst(item, pending_call_t, link);
[eadaeae8]84 return CAP_HANDLE_RAW(hs->call_handle);
[9a1b20c]85}
86
[062d900]87static bool pending_call_key_equal(void *key, const ht_link_t *item)
[9a1b20c]88{
[eadaeae8]89 cap_call_handle_t *chandle = (cap_call_handle_t *) key;
[062d900]90 pending_call_t *hs = hash_table_get_inst(item, pending_call_t, link);
91
[eadaeae8]92 return *chandle == hs->call_handle;
[9a1b20c]93}
94
[062d900]95static hash_table_ops_t pending_call_ops = {
96 .hash = pending_call_hash,
97 .key_hash = pending_call_key_hash,
98 .key_equal = pending_call_key_equal,
[4e00f87]99 .equal = NULL,
100 .remove_callback = NULL
[062d900]101};
102
[9a1b20c]103
[eadaeae8]104void ipcp_connection_set(cap_phone_handle_t phone, int server, proto_t *proto)
[9a1b20c]105{
[eadaeae8]106 // XXX: there is no longer a limit on the number of phones as phones are
107 // now handled using capabilities
108 if (CAP_HANDLE_RAW(phone) < 0 || CAP_HANDLE_RAW(phone) >= MAX_PHONE)
[1433ecda]109 return;
[eadaeae8]110 connections[CAP_HANDLE_RAW(phone)].server = server;
111 connections[CAP_HANDLE_RAW(phone)].proto = proto;
112 have_conn[CAP_HANDLE_RAW(phone)] = 1;
[9a1b20c]113}
114
[eadaeae8]115void ipcp_connection_clear(cap_phone_handle_t phone)
[9a1b20c]116{
[eadaeae8]117 have_conn[CAP_HANDLE_RAW(phone)] = 0;
118 connections[CAP_HANDLE_RAW(phone)].server = 0;
119 connections[CAP_HANDLE_RAW(phone)].proto = NULL;
[9a1b20c]120}
121
[96b02eb9]122static void ipc_m_print(proto_t *proto, sysarg_t method)
[9a1b20c]123{
124 oper_t *oper;
125
[8c125ad]126 /* Try system methods first */
127 oper = proto_get_oper(proto_system, method);
[9a1b20c]128
[8c125ad]129 if (oper == NULL && proto != NULL) {
130 /* Not a system method, try the user protocol. */
131 oper = proto_get_oper(proto, method);
[9a1b20c]132 }
133
[8c125ad]134 if (oper != NULL) {
[7e752b2]135 printf("%s (%" PRIun ")", oper->name, method);
[8c125ad]136 return;
[9a1b20c]137 }
138
[7e752b2]139 printf("%" PRIun, method);
[9a1b20c]140}
141
142void ipcp_init(void)
143{
[abf3564]144 val_type_t arg_def[OPER_MAX_ARGS] = {
145 V_INTEGER,
146 V_INTEGER,
147 V_INTEGER,
148 V_INTEGER,
[40fd6f0]149 V_INTEGER
[abf3564]150 };
151
[8c125ad]152 /*
153 * Create a pseudo-protocol 'unknown' that has no known methods.
154 */
155 proto_unknown = proto_new("unknown");
156
157 /*
158 * Create a pseudo-protocol 'system' defining names of system IPC
159 * methods.
160 */
161 proto_system = proto_new("system");
162
[a3b339b4]163 for (size_t i = 0; i < ipc_methods_len; i++) {
164 oper_t *oper = oper_new(ipc_methods[i].name, OPER_MAX_ARGS,
165 arg_def, V_INTEGER, OPER_MAX_ARGS, arg_def);
166 proto_add_oper(proto_system, ipc_methods[i].number, oper);
[8c125ad]167 }
168
[062d900]169 bool ok = hash_table_create(&pending_calls, 0, 0, &pending_call_ops);
170 assert(ok);
[9a1b20c]171}
172
173void ipcp_cleanup(void)
174{
[8c125ad]175 proto_delete(proto_system);
[9a1b20c]176 hash_table_destroy(&pending_calls);
177}
178
[eadaeae8]179void ipcp_call_out(cap_phone_handle_t phandle, ipc_call_t *call,
180 cap_call_handle_t chandle)
[9a1b20c]181{
182 pending_call_t *pcall;
183 proto_t *proto;
[1643855]184 oper_t *oper;
[96b02eb9]185 sysarg_t *args;
[abf3564]186 int i;
[9a1b20c]187
[eadaeae8]188 if (have_conn[CAP_HANDLE_RAW(phandle)])
189 proto = connections[CAP_HANDLE_RAW(phandle)].proto;
190 else
191 proto = NULL;
[9a1b20c]192
[abf3564]193 args = call->args;
194
[1643855]195 if ((display_mask & DM_IPC) != 0) {
[eed4139]196 printf("Call handle: %p, phone: %p, proto: %s, method: ",
[eadaeae8]197 chandle, phandle, (proto ? proto->name : "n/a"));
[228e490]198 ipc_m_print(proto, IPC_GET_IMETHOD(*call));
[7e752b2]199 printf(" args: (%" PRIun ", %" PRIun ", %" PRIun ", "
200 "%" PRIun ", %" PRIun ")\n",
201 args[1], args[2], args[3], args[4], args[5]);
[1643855]202 }
203
204
205 if ((display_mask & DM_USER) != 0) {
206
207 if (proto != NULL) {
[228e490]208 oper = proto_get_oper(proto, IPC_GET_IMETHOD(*call));
[1643855]209 } else {
210 oper = NULL;
211 }
212
213 if (oper != NULL) {
214
[eadaeae8]215 printf("%s(%p).%s", (proto ? proto->name : "n/a"),
216 phandle, (oper ? oper->name : "unknown"));
[1643855]217
[abf3564]218 putchar('(');
219 for (i = 1; i <= oper->argc; ++i) {
[1433ecda]220 if (i > 1)
221 printf(", ");
[abf3564]222 val_print(args[i], oper->arg_type[i - 1]);
223 }
224 putchar(')');
225
226 if (oper->rv_type == V_VOID && oper->respc == 0) {
227 /*
228 * No response data (typically the task will
229 * not be interested in the response).
230 * We will not display response.
231 */
232 putchar('.');
233 }
234
235 putchar('\n');
[1643855]236 }
[abf3564]237 } else {
238 oper = NULL;
[1643855]239 }
[9a1b20c]240
241 /* Store call in hash table for response matching */
242
243 pcall = malloc(sizeof(pending_call_t));
[eadaeae8]244 pcall->phone_handle = phandle;
[9a1b20c]245 pcall->question = *call;
[eadaeae8]246 pcall->call_handle = chandle;
[abf3564]247 pcall->oper = oper;
[9a1b20c]248
[062d900]249 hash_table_insert(&pending_calls, &pcall->link);
[9a1b20c]250}
251
[eadaeae8]252static void parse_answer(cap_call_handle_t call_handle, pending_call_t *pcall,
[1643855]253 ipc_call_t *answer)
[9a1b20c]254{
[eadaeae8]255 cap_phone_handle_t phone;
[96b02eb9]256 sysarg_t method;
257 sysarg_t service;
[b7fd2a0]258 errno_t retval;
[9a1b20c]259 proto_t *proto;
[eadaeae8]260 cap_phone_handle_t cphone;
[a35b458]261
[96b02eb9]262 sysarg_t *resp;
[abf3564]263 oper_t *oper;
264 int i;
[a35b458]265
[eadaeae8]266 phone = pcall->phone_handle;
[228e490]267 method = IPC_GET_IMETHOD(pcall->question);
[9a1b20c]268 retval = IPC_GET_RETVAL(*answer);
[a35b458]269
[abf3564]270 resp = answer->args;
[a35b458]271
[1643855]272 if ((display_mask & DM_IPC) != 0) {
[eadaeae8]273 printf("Response to %p: retval=%s, args = (%" PRIun ", "
[7e752b2]274 "%" PRIun ", %" PRIun ", %" PRIun ", %" PRIun ")\n",
[eadaeae8]275 call_handle, str_error_name(retval), IPC_GET_ARG1(*answer),
[1ccafee]276 IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
277 IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
[1643855]278 }
[a35b458]279
[1643855]280 if ((display_mask & DM_USER) != 0) {
[abf3564]281 oper = pcall->oper;
[a35b458]282
[79ae36dd]283 if ((oper != NULL) &&
284 ((oper->rv_type != V_VOID) || (oper->respc > 0))) {
[abf3564]285 printf("->");
[a35b458]286
[abf3564]287 if (oper->rv_type != V_VOID) {
288 putchar(' ');
[1569a9b]289 val_print((sysarg_t) retval, oper->rv_type);
[abf3564]290 }
[a35b458]291
[abf3564]292 if (oper->respc > 0) {
293 putchar(' ');
294 putchar('(');
295 for (i = 1; i <= oper->respc; ++i) {
[79ae36dd]296 if (i > 1)
297 printf(", ");
[abf3564]298 val_print(resp[i], oper->resp_type[i - 1]);
299 }
300 putchar(')');
301 }
[a35b458]302
[abf3564]303 putchar('\n');
304 }
[1643855]305 }
[a35b458]306
[79ae36dd]307 if ((phone == PHONE_NS) && (method == IPC_M_CONNECT_ME_TO) &&
308 (retval == 0)) {
[9a1b20c]309 /* Connected to a service (through NS) */
[2133e02]310 service = IPC_GET_ARG2(pcall->question);
[9a1b20c]311 proto = proto_get_by_srv(service);
[79ae36dd]312 if (proto == NULL)
313 proto = proto_unknown;
[a35b458]314
[eadaeae8]315 cphone = (cap_phone_handle_t) IPC_GET_ARG5(*answer);
[1643855]316 if ((display_mask & DM_SYSTEM) != 0) {
[eadaeae8]317 printf("Registering connection (phone %p, protocol: %s)\n", cphone,
[1433ecda]318 proto->name);
[1643855]319 }
[a35b458]320
[9a1b20c]321 ipcp_connection_set(cphone, 0, proto);
322 }
323}
324
[eadaeae8]325void ipcp_call_in(ipc_call_t *call, cap_call_handle_t chandle)
[9a1b20c]326{
[062d900]327 ht_link_t *item;
[9a1b20c]328 pending_call_t *pcall;
[a35b458]329
[40fd6f0]330 if ((call->flags & IPC_CALL_ANSWERED) == 0) {
[9a1b20c]331 /* Not a response */
[1643855]332 if ((display_mask & DM_IPC) != 0) {
[eadaeae8]333 printf("Not a response (handle %p)\n", chandle);
[1643855]334 }
[9a1b20c]335 return;
336 }
[a35b458]337
[eadaeae8]338 item = hash_table_find(&pending_calls, &chandle);
[79ae36dd]339 if (item == NULL)
340 return; /* No matching question found */
[a35b458]341
[1643855]342 /*
343 * Response matched to question.
344 */
[a35b458]345
[062d900]346 pcall = hash_table_get_inst(item, pending_call_t, link);
[eadaeae8]347 hash_table_remove(&pending_calls, &chandle);
[a35b458]348
[eadaeae8]349 parse_answer(chandle, pcall, call);
[9a1b20c]350 free(pcall);
351}
352
[eadaeae8]353void ipcp_hangup(cap_phone_handle_t phone, errno_t rc)
[9a1b20c]354{
[1643855]355 if ((display_mask & DM_SYSTEM) != 0) {
[eadaeae8]356 printf("Hang up phone %p -> %s\n", phone, str_error_name(rc));
[1643855]357 ipcp_connection_clear(phone);
358 }
[9a1b20c]359}
360
361/** @}
362 */
Note: See TracBrowser for help on using the repository browser.