source: mainline/uspace/app/trace/ipcp.c@ 17c14273

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

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • 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.