source: mainline/uspace/app/trace/ipcp.c@ 9a1b20c

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

Merge syscall tracer (trace) and relevant part of udebug interface from tracing to trunk.

  • Property mode set to 100644
File size: 6.5 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 "ipcp.h"
42
43#define IPCP_CALLID_SYNC 0
44
45typedef struct {
46 int phone_hash;
47 ipc_call_t question;
48
49 int call_hash;
50
51 link_t link;
52} pending_call_t;
53
54typedef struct {
55 int server;
56 proto_t *proto;
57} connection_t;
58
59#define MAX_PHONE 64
60connection_t connections[MAX_PHONE];
61int have_conn[MAX_PHONE];
62
63#define PCALL_TABLE_CHAINS 32
64hash_table_t pending_calls;
65
66static hash_index_t pending_call_hash(unsigned long key[]);
67static int pending_call_compare(unsigned long key[], hash_count_t keys,
68 link_t *item);
69static void pending_call_remove_callback(link_t *item);
70
71hash_table_operations_t pending_call_ops = {
72 .hash = pending_call_hash,
73 .compare = pending_call_compare,
74 .remove_callback = pending_call_remove_callback
75};
76
77
78static hash_index_t pending_call_hash(unsigned long key[])
79{
80// printf("pending_call_hash\n");
81 return key[0] % PCALL_TABLE_CHAINS;
82}
83
84static int pending_call_compare(unsigned long key[], hash_count_t keys,
85 link_t *item)
86{
87 pending_call_t *hs;
88
89// printf("pending_call_compare\n");
90 hs = hash_table_get_instance(item, pending_call_t, link);
91
92 return key[0] == hs->call_hash;
93}
94
95static void pending_call_remove_callback(link_t *item)
96{
97// printf("pending_call_remove_callback\n");
98}
99
100
101void ipcp_connection_set(int phone, int server, proto_t *proto)
102{
103 if (phone <0 || phone >= MAX_PHONE) return;
104 connections[phone].server = server;
105 connections[phone].proto = proto;
106 have_conn[phone] = 1;
107}
108
109void ipcp_connection_clear(int phone)
110{
111 have_conn[phone] = 0;
112 connections[phone].server = 0;
113 connections[phone].proto = NULL;
114}
115
116static void ipc_m_print(proto_t *proto, ipcarg_t method)
117{
118 ipc_m_desc_t *desc;
119 oper_t *oper;
120
121 /* FIXME: too slow */
122 desc = ipc_methods;
123 while (desc->number != 0) {
124 if (desc->number == method) {
125 printf("%s (%d)", desc->name, method);
126 return;
127 }
128
129 ++desc;
130 }
131
132 if (proto != NULL) {
133 oper = proto_get_oper(proto, method);
134 if (oper != NULL) {
135 printf("%s (%d)", oper->name, method);
136 return;
137 }
138 }
139
140 printf("%d", method);
141}
142
143void ipcp_init(void)
144{
145 hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
146}
147
148void ipcp_cleanup(void)
149{
150 hash_table_destroy(&pending_calls);
151}
152
153void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
154{
155 pending_call_t *pcall;
156 proto_t *proto;
157 unsigned long key[1];
158
159 if (have_conn[phone]) proto = connections[phone].proto;
160 else proto = NULL;
161
162// printf("ipcp_call_out()\n");
163 printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
164 (proto ? proto->name : "n/a"));
165 ipc_m_print(proto, IPC_GET_METHOD(*call));
166 printf(" args: (%u, %u, %u, %u, %u)\n",
167 IPC_GET_ARG1(*call),
168 IPC_GET_ARG2(*call),
169 IPC_GET_ARG3(*call),
170 IPC_GET_ARG4(*call),
171 IPC_GET_ARG5(*call)
172 );
173
174 /* Store call in hash table for response matching */
175
176 pcall = malloc(sizeof(pending_call_t));
177 pcall->phone_hash = phone;
178 pcall->question = *call;
179 pcall->call_hash = hash;
180
181 key[0] = hash;
182
183 hash_table_insert(&pending_calls, key, &pcall->link);
184}
185
186static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
187{
188 int phone;
189 ipcarg_t method;
190 ipcarg_t service;
191 int retval;
192 static proto_t proto_unknown = { .name = "unknown" };
193 proto_t *proto;
194 int cphone;
195
196// printf("parse_answer\n");
197
198 phone = pcall->phone_hash;
199 method = IPC_GET_METHOD(pcall->question);
200 retval = IPC_GET_RETVAL(*answer);
201 printf("phone=%d, method=%d, retval=%d\n",
202 phone, method, retval);
203
204 if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
205 /* Connected to a service (through NS) */
206 service = IPC_GET_ARG1(pcall->question);
207 proto = proto_get_by_srv(service);
208 if (proto == NULL) proto = &proto_unknown;
209
210 cphone = IPC_GET_ARG5(*answer);
211 printf("registering connection (phone %d, protocol: %s)\n", cphone,
212 proto->name);
213 ipcp_connection_set(cphone, 0, proto);
214 }
215}
216
217void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
218{
219 link_t *item;
220 pending_call_t *pcall;
221 unsigned long key[1];
222
223// printf("ipcp_call_in()\n");
224/* printf("phone: %d, method: ", call->in_phone_hash);
225 ipc_m_print(IPC_GET_METHOD(*call));
226 printf(" args: (%u, %u, %u, %u, %u)\n",
227 IPC_GET_ARG1(*call),
228 IPC_GET_ARG2(*call),
229 IPC_GET_ARG3(*call),
230 IPC_GET_ARG4(*call),
231 IPC_GET_ARG5(*call)
232 );*/
233
234 if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
235 /* Not a response */
236 printf("Not a response (hash %d)\n", hash);
237 return;
238 }
239
240 hash = hash & ~IPC_CALLID_ANSWERED;
241 key[0] = hash;
242
243 item = hash_table_find(&pending_calls, key);
244 if (item == NULL) return; // No matching question found
245
246 pcall = hash_table_get_instance(item, pending_call_t, link);
247
248 printf("response matched to question\n");
249 hash_table_remove(&pending_calls, key, 1);
250
251 parse_answer(pcall, call);
252 free(pcall);
253}
254
255void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
256{
257 ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
258 ipcp_call_in(answer, IPCP_CALLID_SYNC);
259}
260
261void ipcp_hangup(int phone, int rc)
262{
263 printf("hangup phone %d -> %d\n", phone, rc);
264 ipcp_connection_clear(phone);
265}
266
267/** @}
268 */
Note: See TracBrowser for help on using the repository browser.