Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3470 → Rev 3471

/branches/tracing/uspace/app/trace/ipcp.c
38,15 → 38,17
 
#include "ipc_desc.h"
#include "proto.h"
#include "trace.h"
#include "ipcp.h"
 
#define IPCP_CALLID_SYNC 0
 
typedef struct {
int phone_hash;
ipcarg_t phone_hash;
ipc_call_t question;
oper_t *oper;
 
int call_hash;
ipc_callid_t call_hash;
 
link_t link;
} pending_call_t;
63,6 → 65,12
#define PCALL_TABLE_CHAINS 32
hash_table_t pending_calls;
 
/*
* Pseudo-protocols
*/
proto_t *proto_system; /**< Protocol describing system IPC methods. */
proto_t *proto_unknown; /**< Protocol with no known methods. */
 
static hash_index_t pending_call_hash(unsigned long key[]);
static int pending_call_compare(unsigned long key[], hash_count_t keys,
link_t *item);
89,6 → 97,7
// printf("pending_call_compare\n");
hs = hash_table_get_instance(item, pending_call_t, link);
 
// FIXME: this will fail if sizeof(long) < sizeof(void *).
return key[0] == hs->call_hash;
}
 
115,38 → 124,63
 
static void ipc_m_print(proto_t *proto, ipcarg_t method)
{
ipc_m_desc_t *desc;
oper_t *oper;
 
/* FIXME: too slow */
desc = ipc_methods;
while (desc->number != 0) {
if (desc->number == method) {
printf("%s (%d)", desc->name, method);
return;
}
/* Try system methods first */
oper = proto_get_oper(proto_system, method);
 
++desc;
if (oper == NULL && proto != NULL) {
/* Not a system method, try the user protocol. */
oper = proto_get_oper(proto, method);
}
 
if (proto != NULL) {
oper = proto_get_oper(proto, method);
if (oper != NULL) {
printf("%s (%d)", oper->name, method);
return;
}
if (oper != NULL) {
printf("%s (%ld)", oper->name, method);
return;
}
 
printf("%d", method);
printf("%ld", method);
}
 
void ipcp_init(void)
{
ipc_m_desc_t *desc;
oper_t *oper;
 
val_type_t arg_def[OPER_MAX_ARGS] = {
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER
};
 
/*
* Create a pseudo-protocol 'unknown' that has no known methods.
*/
proto_unknown = proto_new("unknown");
 
/*
* Create a pseudo-protocol 'system' defining names of system IPC
* methods.
*/
proto_system = proto_new("system");
 
desc = ipc_methods;
while (desc->number != 0) {
oper = oper_new(desc->name, OPER_MAX_ARGS, arg_def, V_INTEGER,
OPER_MAX_ARGS, arg_def);
proto_add_oper(proto_system, desc->number, oper);
 
++desc;
}
 
hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
}
 
void ipcp_cleanup(void)
{
proto_delete(proto_system);
hash_table_destroy(&pending_calls);
}
 
155,22 → 189,59
pending_call_t *pcall;
proto_t *proto;
unsigned long key[1];
oper_t *oper;
ipcarg_t *args;
int i;
 
if (have_conn[phone]) proto = connections[phone].proto;
else proto = NULL;
 
// printf("ipcp_call_out()\n");
printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
(proto ? proto->name : "n/a"));
ipc_m_print(proto, IPC_GET_METHOD(*call));
printf(" args: (%u, %u, %u, %u, %u)\n",
IPC_GET_ARG1(*call),
IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call),
IPC_GET_ARG4(*call),
IPC_GET_ARG5(*call)
);
args = call->args;
 
if ((display_mask & DM_IPC) != 0) {
printf("Call ID: 0x%lx, phone: %d, proto: %s, method: ", hash,
phone, (proto ? proto->name : "n/a"));
ipc_m_print(proto, IPC_GET_METHOD(*call));
printf(" args: (%lu, %lu, %lu, %lu, %lu)\n", args[1], args[2],
args[3], args[4], args[5]);
}
 
 
if ((display_mask & DM_USER) != 0) {
 
if (proto != NULL) {
oper = proto_get_oper(proto, IPC_GET_METHOD(*call));
} else {
oper = NULL;
}
 
if (oper != NULL) {
 
printf("%s(%d).%s", (proto ? proto->name : "n/a"),
phone, (oper ? oper->name : "unknown"));
 
putchar('(');
for (i = 1; i <= oper->argc; ++i) {
if (i > 1) printf(", ");
val_print(args[i], oper->arg_type[i - 1]);
}
putchar(')');
 
if (oper->rv_type == V_VOID && oper->respc == 0) {
/*
* No response data (typically the task will
* not be interested in the response).
* We will not display response.
*/
putchar('.');
}
 
putchar('\n');
}
} else {
oper = NULL;
}
 
/* Store call in hash table for response matching */
 
pcall = malloc(sizeof(pending_call_t));
177,6 → 248,7
pcall->phone_hash = phone;
pcall->question = *call;
pcall->call_hash = hash;
pcall->oper = oper;
 
key[0] = hash;
 
183,33 → 255,71
hash_table_insert(&pending_calls, key, &pcall->link);
}
 
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
static void parse_answer(ipc_callid_t hash, pending_call_t *pcall,
ipc_call_t *answer)
{
int phone;
ipcarg_t phone;
ipcarg_t method;
ipcarg_t service;
int retval;
static proto_t proto_unknown = { .name = "unknown" };
ipcarg_t retval;
proto_t *proto;
int cphone;
 
ipcarg_t *resp;
oper_t *oper;
int i;
 
// printf("parse_answer\n");
 
phone = pcall->phone_hash;
method = IPC_GET_METHOD(pcall->question);
retval = IPC_GET_RETVAL(*answer);
printf("phone=%d, method=%d, retval=%d\n",
phone, method, retval);
 
resp = answer->args;
 
if ((display_mask & DM_IPC) != 0) {
printf("Response to 0x%lx: retval=%ld, args = (%lu, %lu, %lu, %lu, %lu)\n",
hash, retval, IPC_GET_ARG1(*answer),
IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
}
 
if ((display_mask & DM_USER) != 0) {
oper = pcall->oper;
 
if (oper != NULL && (oper->rv_type != V_VOID || oper->respc > 0)) {
printf("->");
 
if (oper->rv_type != V_VOID) {
putchar(' ');
val_print(retval, oper->rv_type);
}
if (oper->respc > 0) {
putchar(' ');
putchar('(');
for (i = 1; i <= oper->respc; ++i) {
if (i > 1) printf(", ");
val_print(resp[i], oper->resp_type[i - 1]);
}
putchar(')');
}
 
putchar('\n');
}
}
 
if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
/* Connected to a service (through NS) */
service = IPC_GET_ARG1(pcall->question);
proto = proto_get_by_srv(service);
if (proto == NULL) proto = &proto_unknown;
if (proto == NULL) proto = proto_unknown;
 
cphone = IPC_GET_ARG5(*answer);
printf("registering connection (phone %d, protocol: %s)\n", cphone,
proto->name);
if ((display_mask & DM_SYSTEM) != 0) {
printf("Registering connection (phone %d, protocol: %s)\n", cphone,
proto->name);
}
ipcp_connection_set(cphone, 0, proto);
}
}
221,19 → 331,12
unsigned long key[1];
 
// printf("ipcp_call_in()\n");
/* printf("phone: %d, method: ", call->in_phone_hash);
ipc_m_print(IPC_GET_METHOD(*call));
printf(" args: (%u, %u, %u, %u, %u)\n",
IPC_GET_ARG1(*call),
IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call),
IPC_GET_ARG4(*call),
IPC_GET_ARG5(*call)
);*/
 
if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
/* Not a response */
printf("Not a response (hash %d)\n", hash);
if ((display_mask & DM_IPC) != 0) {
printf("Not a response (hash 0x%lx)\n", hash);
}
return;
}
 
242,13 → 345,15
 
item = hash_table_find(&pending_calls, key);
if (item == NULL) return; // No matching question found
 
/*
* Response matched to question.
*/
pcall = hash_table_get_instance(item, pending_call_t, link);
 
printf("response matched to question\n");
hash_table_remove(&pending_calls, key, 1);
 
parse_answer(pcall, call);
parse_answer(hash, pcall, call);
free(pcall);
}
 
260,8 → 365,10
 
void ipcp_hangup(int phone, int rc)
{
printf("hangup phone %d -> %d\n", phone, rc);
ipcp_connection_clear(phone);
if ((display_mask & DM_SYSTEM) != 0) {
printf("Hang phone %d up -> %d\n", phone, rc);
ipcp_connection_clear(phone);
}
}
 
/** @}