Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2620 → Rev 2621

/trunk/uspace/lib/libc/generic/async.c
101,6 → 101,7
#include <errno.h>
#include <sys/time.h>
#include <arch/barrier.h>
#include <bool.h>
 
atomic_t async_futex = FUTEX_INITIALIZER;
static hash_table_t conn_hash_table;
175,7 → 176,7
* If true, it is forbidden to use async_req functions and all preemption is
* disabled.
*/
__thread int in_interrupt_handler;
__thread int _in_interrupt_handler;
 
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
190,6 → 191,17
*/
static async_client_conn_t interrupt_received = default_interrupt_received;
 
/*
* Getter for _in_interrupt_handler. We need to export the value of this thread
* local variable to other modules, but the binutils 2.18 linkers die on an
* attempt to export this symbol in the header file. For now, consider this as a
* workaround.
*/
bool in_interrupt_handler(void)
{
return _in_interrupt_handler;
}
 
#define CONN_HASH_TABLE_CHAINS 32
 
/** Compute hash into the connection hash table based on the source phone hash.
517,9 → 529,9
{
/* Unrouted call - do some default behaviour */
if ((callid & IPC_CALLID_NOTIFICATION)) {
in_interrupt_handler = 1;
_in_interrupt_handler = 1;
(*interrupt_received)(callid, call);
in_interrupt_handler = 0;
_in_interrupt_handler = 0;
return;
}
 
716,17 → 728,19
* @param method Service-defined method.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param dataptr If non-NULL, storage where the reply data will be
* stored.
*
* @return Hash of the sent message.
*/
aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
ipc_call_t *dataptr)
aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr)
{
amsg_t *msg;
 
if (in_interrupt_handler) {
if (_in_interrupt_handler) {
printf("Cannot send asynchronous request in interrupt "
"handler.\n");
_exit(1);
739,7 → 753,8
/* We may sleep in the next method, but it will use its own mechanism */
msg->wdata.active = 1;
ipc_call_async_2(phoneid, method, arg1, arg2, msg, reply_received, 1);
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
reply_received, 1);
 
return (aid_t) msg;
}
754,17 → 769,20
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param arg5 Service-defined payload argument.
* @param dataptr If non-NULL, storage where the reply data will be
* stored.
*
* @return Hash of the sent message.
*/
aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
ipcarg_t arg3, ipc_call_t *dataptr)
aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5,
ipc_call_t *dataptr)
{
amsg_t *msg;
 
if (in_interrupt_handler) {
if (_in_interrupt_handler) {
printf("Cannot send asynchronous request in interrupt "
"handler.\n");
_exit(1);
776,10 → 794,10
 
/* We may sleep in next method, but it will use its own mechanism */
msg->wdata.active = 1;
ipc_call_async_3(phoneid, method, arg1, arg2, arg3, msg, reply_received,
1);
 
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
reply_received, 1);
 
return (aid_t) msg;
}
 
866,7 → 884,7
{
amsg_t *msg;
if (in_interrupt_handler) {
if (_in_interrupt_handler) {
printf("Cannot call async_usleep in interrupt handler.\n");
_exit(1);
}
908,18 → 926,88
interrupt_received = conn;
}
 
/* Primitive functions for simple communication */
void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3)
/** Pseudo-synchronous message sending - fast version.
*
* Send message asynchronously and return only after the reply arrives.
*
* This function can only transfer 4 register payload arguments. For
* transferring more arguments, see the slower async_req_slow().
*
* @param phoneid Hash of the phone through which to make the call.
* @param method Method of the call.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param r1 If non-NULL, storage for the 1st reply argument.
* @param r2 If non-NULL, storage for the 2nd reply argument.
* @param r3 If non-NULL, storage for the 3rd reply argument.
* @param r4 If non-NULL, storage for the 4th reply argument.
* @param r5 If non-NULL, storage for the 5th reply argument.
* @return Return code of the reply or a negative error code.
*/
ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2,
ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5)
{
ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL,
!in_interrupt_handler);
ipc_call_t result;
ipcarg_t rc;
 
aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
&result);
async_wait_for(eid, &rc);
if (r1)
*r1 = IPC_GET_ARG1(result);
if (r2)
*r2 = IPC_GET_ARG2(result);
if (r3)
*r3 = IPC_GET_ARG3(result);
if (r4)
*r4 = IPC_GET_ARG4(result);
if (r5)
*r5 = IPC_GET_ARG5(result);
return rc;
}
 
void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)
/** Pseudo-synchronous message sending - slow version.
*
* Send message asynchronously and return only after the reply arrives.
*
* @param phoneid Hash of the phone through which to make the call.
* @param method Method of the call.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param arg5 Service-defined payload argument.
* @param r1 If non-NULL, storage for the 1st reply argument.
* @param r2 If non-NULL, storage for the 2nd reply argument.
* @param r3 If non-NULL, storage for the 3rd reply argument.
* @param r4 If non-NULL, storage for the 4th reply argument.
* @param r5 If non-NULL, storage for the 5th reply argument.
* @return Return code of the reply or a negative error code.
*/
ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1,
ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5)
{
ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL,
!in_interrupt_handler);
ipc_call_t result;
ipcarg_t rc;
 
aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
&result);
async_wait_for(eid, &rc);
if (r1)
*r1 = IPC_GET_ARG1(result);
if (r2)
*r2 = IPC_GET_ARG2(result);
if (r3)
*r3 = IPC_GET_ARG3(result);
if (r4)
*r4 = IPC_GET_ARG4(result);
if (r5)
*r5 = IPC_GET_ARG5(result);
return rc;
}
 
/** @}