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