source: mainline/uspace/app/trace/ipcp.c@ f7176b1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f7176b1 was abf3564, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

trace: Decode protocol-level call arguments, response retvals and arguments.

  • Property mode set to 100644
File size: 8.8 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 <libadt/hash_table.h>
38
39#include "ipc_desc.h"
40#include "proto.h"
41#include "trace.h"
42#include "ipcp.h"
43
44#define IPCP_CALLID_SYNC 0
45
46typedef struct {
47 int phone_hash;
48 ipc_call_t question;
49 oper_t *oper;
50
51 int call_hash;
52
53 link_t link;
54} pending_call_t;
55
56typedef struct {
57 int server;
58 proto_t *proto;
59} connection_t;
60
61#define MAX_PHONE 64
62connection_t connections[MAX_PHONE];
63int have_conn[MAX_PHONE];
64
65#define PCALL_TABLE_CHAINS 32
66hash_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
74static hash_index_t pending_call_hash(unsigned long key[]);
75static int pending_call_compare(unsigned long key[], hash_count_t keys,
76 link_t *item);
77static void pending_call_remove_callback(link_t *item);
78
79hash_table_operations_t pending_call_ops = {
80 .hash = pending_call_hash,
81 .compare = pending_call_compare,
82 .remove_callback = pending_call_remove_callback
83};
84
85
86static hash_index_t pending_call_hash(unsigned long key[])
87{
88// printf("pending_call_hash\n");
89 return key[0] % PCALL_TABLE_CHAINS;
90}
91
92static int pending_call_compare(unsigned long key[], hash_count_t keys,
93 link_t *item)
94{
95 pending_call_t *hs;
96
97// printf("pending_call_compare\n");
98 hs = hash_table_get_instance(item, pending_call_t, link);
99
100 return key[0] == hs->call_hash;
101}
102
103static void pending_call_remove_callback(link_t *item)
104{
105// printf("pending_call_remove_callback\n");
106}
107
108
109void ipcp_connection_set(int phone, int server, proto_t *proto)
110{
111 if (phone <0 || phone >= MAX_PHONE) return;
112 connections[phone].server = server;
113 connections[phone].proto = proto;
114 have_conn[phone] = 1;
115}
116
117void ipcp_connection_clear(int phone)
118{
119 have_conn[phone] = 0;
120 connections[phone].server = 0;
121 connections[phone].proto = NULL;
122}
123
124static void ipc_m_print(proto_t *proto, ipcarg_t method)
125{
126 oper_t *oper;
127
128 /* Try system methods first */
129 oper = proto_get_oper(proto_system, method);
130
131 if (oper == NULL && proto != NULL) {
132 /* Not a system method, try the user protocol. */
133 oper = proto_get_oper(proto, method);
134 }
135
136 if (oper != NULL) {
137 printf("%s (%d)", oper->name, method);
138 return;
139 }
140
141 printf("%d", method);
142}
143
144void ipcp_init(void)
145{
146 ipc_m_desc_t *desc;
147 oper_t *oper;
148
149 val_type_t arg_def[OPER_MAX_ARGS] = {
150 V_INTEGER,
151 V_INTEGER,
152 V_INTEGER,
153 V_INTEGER,
154 V_INTEGER
155 };
156
157 /*
158 * Create a pseudo-protocol 'unknown' that has no known methods.
159 */
160 proto_unknown = proto_new("unknown");
161
162 /*
163 * Create a pseudo-protocol 'system' defining names of system IPC
164 * methods.
165 */
166 proto_system = proto_new("system");
167
168 desc = ipc_methods;
169 while (desc->number != 0) {
170 oper = oper_new(desc->name, OPER_MAX_ARGS, arg_def, V_INTEGER,
171 OPER_MAX_ARGS, arg_def);
172 proto_add_oper(proto_system, desc->number, oper);
173
174 ++desc;
175 }
176
177 hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
178}
179
180void ipcp_cleanup(void)
181{
182 proto_delete(proto_system);
183 hash_table_destroy(&pending_calls);
184}
185
186void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
187{
188 pending_call_t *pcall;
189 proto_t *proto;
190 unsigned long key[1];
191 oper_t *oper;
192 ipcarg_t *args;
193 int i;
194
195 if (have_conn[phone]) proto = connections[phone].proto;
196 else proto = NULL;
197
198 args = call->args;
199
200 if ((display_mask & DM_IPC) != 0) {
201 printf("Call ID: 0x%x, phone: %d, proto: %s, method: ", hash,
202 phone, (proto ? proto->name : "n/a"));
203 ipc_m_print(proto, IPC_GET_METHOD(*call));
204 printf(" args: (%u, %u, %u, %u, %u)\n", args[1], args[2],
205 args[3], args[4], args[5]);
206 }
207
208
209 if ((display_mask & DM_USER) != 0) {
210
211 if (proto != NULL) {
212 oper = proto_get_oper(proto, IPC_GET_METHOD(*call));
213 } else {
214 oper = NULL;
215 }
216
217 if (oper != NULL) {
218
219 printf("%s(%d).%s", (proto ? proto->name : "n/a"),
220 phone, (oper ? oper->name : "unknown"));
221
222 putchar('(');
223 for (i = 1; i <= oper->argc; ++i) {
224 if (i > 1) printf(", ");
225 val_print(args[i], oper->arg_type[i - 1]);
226 }
227 putchar(')');
228
229 if (oper->rv_type == V_VOID && oper->respc == 0) {
230 /*
231 * No response data (typically the task will
232 * not be interested in the response).
233 * We will not display response.
234 */
235 putchar('.');
236 }
237
238 putchar('\n');
239 }
240 } else {
241 oper = NULL;
242 }
243
244 /* Store call in hash table for response matching */
245
246 pcall = malloc(sizeof(pending_call_t));
247 pcall->phone_hash = phone;
248 pcall->question = *call;
249 pcall->call_hash = hash;
250 pcall->oper = oper;
251
252 key[0] = hash;
253
254 hash_table_insert(&pending_calls, key, &pcall->link);
255}
256
257static void parse_answer(ipc_callid_t hash, pending_call_t *pcall,
258 ipc_call_t *answer)
259{
260 int phone;
261 ipcarg_t method;
262 ipcarg_t service;
263 int retval;
264 proto_t *proto;
265 int cphone;
266
267 ipcarg_t *resp;
268 oper_t *oper;
269 int i;
270
271// printf("parse_answer\n");
272
273 phone = pcall->phone_hash;
274 method = IPC_GET_METHOD(pcall->question);
275 retval = IPC_GET_RETVAL(*answer);
276
277 resp = answer->args;
278
279 if ((display_mask & DM_IPC) != 0) {
280 printf("Response to 0x%x: retval=%d, args = (%u, %u, %u, %u, %u)\n",
281 hash, retval, IPC_GET_ARG1(*answer),
282 IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
283 IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
284 }
285
286 if ((display_mask & DM_USER) != 0) {
287 oper = pcall->oper;
288
289 if (oper->rv_type != V_VOID || oper->respc > 0) {
290 printf("->");
291
292 if (oper->rv_type != V_VOID) {
293 putchar(' ');
294 val_print(retval, oper->rv_type);
295 }
296
297 if (oper->respc > 0) {
298 putchar(' ');
299 putchar('(');
300 for (i = 1; i <= oper->respc; ++i) {
301 if (i > 1) printf(", ");
302 val_print(resp[i], oper->resp_type[i - 1]);
303 }
304 putchar(')');
305 }
306
307 putchar('\n');
308 }
309 }
310
311 if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
312 /* Connected to a service (through NS) */
313 service = IPC_GET_ARG1(pcall->question);
314 proto = proto_get_by_srv(service);
315 if (proto == NULL) proto = proto_unknown;
316
317 cphone = IPC_GET_ARG5(*answer);
318 if ((display_mask & DM_SYSTEM) != 0) {
319 printf("Registering connection (phone %d, protocol: %s)\n", cphone,
320 proto->name);
321 }
322 ipcp_connection_set(cphone, 0, proto);
323 }
324}
325
326void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
327{
328 link_t *item;
329 pending_call_t *pcall;
330 unsigned long key[1];
331
332// printf("ipcp_call_in()\n");
333/* printf("phone: %d, method: ", call->in_phone_hash);
334 ipc_m_print(IPC_GET_METHOD(*call));
335 printf(" args: (%u, %u, %u, %u, %u)\n",
336 IPC_GET_ARG1(*call),
337 IPC_GET_ARG2(*call),
338 IPC_GET_ARG3(*call),
339 IPC_GET_ARG4(*call),
340 IPC_GET_ARG5(*call)
341 );*/
342
343 if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
344 /* Not a response */
345 if ((display_mask & DM_IPC) != 0) {
346 printf("Not a response (hash %d)\n", hash);
347 }
348 return;
349 }
350
351 hash = hash & ~IPC_CALLID_ANSWERED;
352 key[0] = hash;
353
354 item = hash_table_find(&pending_calls, key);
355 if (item == NULL) return; // No matching question found
356
357 /*
358 * Response matched to question.
359 */
360
361 pcall = hash_table_get_instance(item, pending_call_t, link);
362 hash_table_remove(&pending_calls, key, 1);
363
364 parse_answer(hash, pcall, call);
365 free(pcall);
366}
367
368void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
369{
370 ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
371 ipcp_call_in(answer, IPCP_CALLID_SYNC);
372}
373
374void ipcp_hangup(int phone, int rc)
375{
376 if ((display_mask & DM_SYSTEM) != 0) {
377 printf("Hang phone %d up -> %d\n", phone, rc);
378 ipcp_connection_clear(phone);
379 }
380}
381
382/** @}
383 */
Note: See TracBrowser for help on using the repository browser.