Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2618 → Rev 2619

/trunk/uspace/lib/libc/include/ipc/ipc.h
190,13 → 190,29
}
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data);
 
#define ipc_answer_fast_0(callid, retval) \
ipc_answer_fast((callid), (retval), 0, 0)
#define ipc_answer_fast_1(callid, retval, arg1) \
ipc_answer_fast((callid), (retval), (arg1), 0)
/*
* User-friendly wrappers for ipc_answer_fast() and ipc_answer_slow().
* They are in the form of ipc_answer_m(), where m is the number of return
* arguments. The macros decide between the fast and the slow version according
* to m.
*/
#define ipc_answer_0(callid, retval) \
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
#define ipc_answer_1(callid, retval, arg1) \
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
#define ipc_answer_2(callid, retval, arg1, arg2) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
#define ipc_answer_3(callid, retval, arg1, arg2, arg3) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
#define ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
 
extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval,
ipcarg_t arg1, ipcarg_t arg2);
extern ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call);
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4);
extern ipcarg_t ipc_answer_slow(ipc_callid_t callid, ipcarg_t retval,
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5);
 
/*
* User-friendly wrappers for ipc_call_async_fast() and ipc_call_async_slow().
244,10 → 260,8
extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method,
ipcarg_t arg1);
extern int ipc_data_send(int phoneid, void *src, size_t size);
extern int ipc_data_receive(ipc_callid_t *callid, ipc_call_t *call, void **dst,
size_t *size);
extern ipcarg_t ipc_data_deliver(ipc_callid_t callid, ipc_call_t *call,
void *dst, size_t size);
extern int ipc_data_receive(ipc_callid_t *callid, void **dst, size_t *size);
extern ipcarg_t ipc_data_deliver(ipc_callid_t callid, void *dst, size_t size);
 
#endif
 
/trunk/uspace/lib/libc/generic/ipc.c
375,33 → 375,50
 
/** Answer a received call - fast version.
*
* The fast answer makes use of passing retval and first two arguments in
* registers. If you need to return more, use the ipc_answer() instead.
* The fast answer makes use of passing retval and first four arguments in
* registers. If you need to return more, use the ipc_answer_slow() instead.
*
* @param callid Hash of the call being answered.
* @param retval Return value.
* @param arg1 First return argument.
* @param arg2 Second return argument.
* @param arg3 Third return argument.
* @param arg4 Fourth return argument.
*
* @return Zero on success or a value from @ref errno.h on failure.
*/
ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
ipcarg_t arg2)
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4)
{
return __SYSCALL4(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2);
return __SYSCALL6(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2, arg3,
arg4);
}
 
/** Answer a received call - full version.
/** Answer a received call - slow full version.
*
* @param callid Hash of the call being answered.
* @param call Call structure with the answer.
* Must be already initialized by the responder.
* @param retval Return value.
* @param arg1 First return argument.
* @param arg2 Second return argument.
* @param arg3 Third return argument.
* @param arg4 Fourth return argument.
* @param arg5 Fifth return argument.
*
* @return Zero on success or a value from @ref errno.h on failure.
*/
ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call)
ipcarg_t ipc_answer_slow(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5)
{
return __SYSCALL2(SYS_IPC_ANSWER, callid, (sysarg_t) call);
ipc_call_t data;
 
IPC_SET_RETVAL(data, retval);
IPC_SET_ARG1(data, arg1);
IPC_SET_ARG2(data, arg2);
IPC_SET_ARG3(data, arg3);
IPC_SET_ARG4(data, arg4);
IPC_SET_ARG5(data, arg5);
 
return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data);
}
 
 
658,7 → 675,6
*
* @param callid Storage where the hash of the IPC_M_DATA_SEND call will
* be stored.
* @param call Storage where the incoming call will be stored.
* @param dst Storage where the suggested destination address will
* be stored. May be NULL.
* @param size Storage where the suggested size will be stored. May be
666,19 → 682,19
*
* @return Non-zero on success, zero on failure.
*/
int ipc_data_receive(ipc_callid_t *callid, ipc_call_t *call, void **dst,
size_t *size)
int ipc_data_receive(ipc_callid_t *callid, void **dst, size_t *size)
{
ipc_call_t data;
assert(callid);
assert(call);
 
*callid = async_get_call(call);
if (IPC_GET_METHOD(*call) != IPC_M_DATA_SEND)
*callid = async_get_call(&data);
if (IPC_GET_METHOD(data) != IPC_M_DATA_SEND)
return 0;
if (dst)
*dst = (void *) IPC_GET_ARG1(*call);
*dst = (void *) IPC_GET_ARG1(data);
if (size)
*size = (size_t) IPC_GET_ARG3(*call);
*size = (size_t) IPC_GET_ARG3(data);
return 1;
}
 
688,19 → 704,14
* so that the user doesn't have to remember the meaning of each IPC argument.
*
* @param callid Hash of the IPC_M_DATA_SEND call to answer.
* @param call Call structure with the request.
* @param dst Final destination address for the IPC_M_DATA_SEND call.
* @param size Final size for the IPC_M_DATA_SEND call.
*
* @return Zero on success or a value from @ref errno.h on failure.
*/
ipcarg_t ipc_data_deliver(ipc_callid_t callid, ipc_call_t *call, void *dst,
size_t size)
ipcarg_t ipc_data_deliver(ipc_callid_t callid, void *dst, size_t size)
{
IPC_SET_RETVAL(*call, EOK);
IPC_SET_ARG1(*call, (ipcarg_t) dst);
IPC_SET_ARG3(*call, (ipcarg_t) size);
return ipc_answer(callid, call);
return ipc_answer_3(callid, EOK, (ipcarg_t) dst, 0, (ipcarg_t) size);
}
/** @}
/trunk/uspace/lib/libc/generic/async.c
75,14 → 75,14
* my_client_connection(icallid, *icall)
* {
* if (want_refuse) {
* ipc_answer_fast(icallid, ELIMIT, 0, 0);
* ipc_answer_0(icallid, ELIMIT);
* return;
* }
* ipc_answer_fast(icallid, EOK, 0, 0);
* ipc_answer_0(icallid, EOK);
*
* callid = async_get_call(&call);
* handle_call(callid, call);
* ipc_answer_fast(callid, 1, 2, 3);
* ipc_answer_2(callid, 1, 2, 3);
*
* callid = async_get_call(&call);
* ....
395,7 → 395,7
*/
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
{
ipc_answer_fast(callid, ENOENT, 0, 0);
ipc_answer_0(callid, ENOENT);
}
 
/** Default fibril function that gets called to handle interrupt notifications.
440,11 → 440,11
list_remove(&msg->link);
if (msg->callid == FIBRIL_connection->close_callid)
close_answered = 1;
ipc_answer_fast(msg->callid, EHANGUP, 0, 0);
ipc_answer_0(msg->callid, EHANGUP);
free(msg);
}
if (FIBRIL_connection->close_callid)
ipc_answer_fast(FIBRIL_connection->close_callid, 0, 0, 0);
ipc_answer_0(FIBRIL_connection->close_callid, EOK);
return 0;
}
475,7 → 475,7
conn = malloc(sizeof(*conn));
if (!conn) {
if (callid)
ipc_answer_fast(callid, ENOMEM, 0, 0);
ipc_answer_0(callid, ENOMEM);
return NULL;
}
conn->in_phone_hash = in_phone_hash;
491,7 → 491,7
if (!conn->wdata.fid) {
free(conn);
if (callid)
ipc_answer_fast(callid, ENOMEM, 0, 0);
ipc_answer_0(callid, ENOMEM);
return NULL;
}
/* Add connection to the connection hash table */
536,7 → 536,7
return;
 
/* Unknown call from unknown phone - hang it up */
ipc_answer_fast(callid, EHANGUP, 0, 0);
ipc_answer_0(callid, EHANGUP);
}
 
/** Fire all timeouts that expired. */