HelenOS sources
This source file includes following definitions.
- amsg_create
- amsg_destroy
- __async_client_init
- __async_client_fini
- async_reply_received
- async_send_fast
- async_send_slow
- async_send_0
- async_send_1
- async_send_2
- async_send_3
- async_send_4
- async_send_5
- async_wait_for
- async_wait_timeout
- async_forget
- async_req_fast
- async_req_slow
- async_req_0_0
- async_req_0_1
- async_req_0_2
- async_req_0_3
- async_req_0_4
- async_req_0_5
- async_req_1_0
- async_req_1_1
- async_req_1_2
- async_req_1_3
- async_req_1_4
- async_req_1_5
- async_req_2_0
- async_req_2_1
- async_req_2_2
- async_req_2_3
- async_req_2_4
- async_req_2_5
- async_req_3_0
- async_req_3_1
- async_req_3_2
- async_req_3_3
- async_req_3_4
- async_req_3_5
- async_req_4_0
- async_req_4_1
- async_req_4_2
- async_req_4_3
- async_req_4_4
- async_req_4_5
- async_req_5_0
- async_req_5_1
- async_req_5_2
- async_req_5_3
- async_req_5_4
- async_req_5_5
- async_msg_0
- async_msg_1
- async_msg_2
- async_msg_3
- async_msg_4
- async_msg_5
- async_connect_me_to_internal
- async_connect_me_to
- async_sess_args_set
- async_connect_me_to_blocking
- async_connect_kbox
- async_hangup_internal
- async_hangup
- async_exchange_begin
- async_exchange_end
- async_share_in_start
- async_share_in_start_0_0
- async_share_in_start_0_1
- async_share_in_start_1_0
- async_share_in_start_1_1
- async_share_out_start
- async_data_read
- async_data_read_start
- async_data_write_start
- async_state_change_start
- async_remote_state_acquire
- async_remote_state_update
- async_remote_state_release
- async_remote_state_release_exchange
- async_as_area_create
#define _LIBC_ASYNC_C_
#include <ipc/ipc.h>
#include <async.h>
#include "../private/async.h"
#include "../private/ns.h"
#undef _LIBC_ASYNC_C_
#include <ipc/irq.h>
#include <ipc/event.h>
#include <fibril.h>
#include <adt/hash_table.h>
#include <adt/hash.h>
#include <adt/list.h>
#include <assert.h>
#include <errno.h>
#include <time.h>
#include <barrier.h>
#include <stdbool.h>
#include <stdlib.h>
#include <mem.h>
#include <stdlib.h>
#include <macros.h>
#include <as.h>
#include <abi/mm/as.h>
#include "../private/libc.h"
#include "../private/fibril.h"
static fibril_rmutex_t message_mutex;
async_sess_t session_ns;
typedef struct {
fibril_event_t received;
bool done;
bool forget;
ipc_call_t *dataptr;
errno_t retval;
} amsg_t;
static amsg_t *amsg_create(void)
{
return calloc(1, sizeof(amsg_t));
}
static void amsg_destroy(amsg_t *msg)
{
free(msg);
}
static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);
static LIST_INITIALIZE(inactive_exch_list);
static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
void __async_client_init(void)
{
if (fibril_rmutex_initialize(&message_mutex) != EOK)
abort();
session_ns.iface = 0;
session_ns.mgmt = EXCHANGE_ATOMIC;
session_ns.phone = PHONE_NS;
session_ns.arg1 = 0;
session_ns.arg2 = 0;
session_ns.arg3 = 0;
fibril_mutex_initialize(&session_ns.remote_state_mtx);
session_ns.remote_state_data = NULL;
list_initialize(&session_ns.exch_list);
fibril_mutex_initialize(&session_ns.mutex);
session_ns.exchanges = 0;
}
void __async_client_fini(void)
{
fibril_rmutex_destroy(&message_mutex);
}
void async_reply_received(ipc_call_t *data)
{
amsg_t *msg = (amsg_t *) data->answer_label;
if (!msg)
return;
fibril_rmutex_lock(&message_mutex);
msg->retval = ipc_get_retval(data);
if ((msg->dataptr) && (data))
*msg->dataptr = *data;
msg->done = true;
if (msg->forget) {
amsg_destroy(msg);
} else {
fibril_notify(&msg->received);
}
fibril_rmutex_unlock(&message_mutex);
}
static aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
{
if (exch == NULL)
return 0;
amsg_t *msg = amsg_create();
if (msg == NULL)
return 0;
msg->dataptr = dataptr;
errno_t rc = ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3,
arg4, msg);
if (rc != EOK) {
msg->retval = rc;
msg->done = true;
}
return (aid_t) msg;
}
static aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
ipc_call_t *dataptr)
{
if (exch == NULL)
return 0;
amsg_t *msg = amsg_create();
if (msg == NULL)
return 0;
msg->dataptr = dataptr;
errno_t rc = ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3,
arg4, arg5, msg);
if (rc != EOK) {
msg->retval = rc;
msg->done = true;
}
return (aid_t) msg;
}
aid_t async_send_0(async_exch_t *exch, sysarg_t imethod, ipc_call_t *dataptr)
{
return async_send_fast(exch, imethod, 0, 0, 0, 0, dataptr);
}
aid_t async_send_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
ipc_call_t *dataptr)
{
return async_send_fast(exch, imethod, arg1, 0, 0, 0, dataptr);
}
aid_t async_send_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, ipc_call_t *dataptr)
{
return async_send_fast(exch, imethod, arg1, arg2, 0, 0, dataptr);
}
aid_t async_send_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, ipc_call_t *dataptr)
{
return async_send_fast(exch, imethod, arg1, arg2, arg3, 0, dataptr);
}
aid_t async_send_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
{
return async_send_fast(exch, imethod, arg1, arg2, arg3, arg4, dataptr);
}
aid_t async_send_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
ipc_call_t *dataptr)
{
return async_send_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5,
dataptr);
}
void async_wait_for(aid_t amsgid, errno_t *retval)
{
if (amsgid == 0) {
if (retval)
*retval = ENOMEM;
return;
}
amsg_t *msg = (amsg_t *) amsgid;
fibril_wait_for(&msg->received);
if (retval)
*retval = msg->retval;
amsg_destroy(msg);
}
errno_t async_wait_timeout(aid_t amsgid, errno_t *retval, usec_t timeout)
{
if (amsgid == 0) {
if (retval)
*retval = ENOMEM;
return EOK;
}
amsg_t *msg = (amsg_t *) amsgid;
if (timeout < 0)
timeout = 0;
struct timespec expires;
getuptime(&expires);
ts_add_diff(&expires, USEC2NSEC(timeout));
errno_t rc = fibril_wait_timeout(&msg->received, &expires);
if (rc != EOK)
return rc;
if (retval)
*retval = msg->retval;
amsg_destroy(msg);
return EOK;
}
void async_forget(aid_t amsgid)
{
if (amsgid == 0)
return;
amsg_t *msg = (amsg_t *) amsgid;
assert(!msg->forget);
fibril_rmutex_lock(&message_mutex);
if (msg->done) {
amsg_destroy(msg);
} else {
msg->dataptr = NULL;
msg->forget = true;
}
fibril_rmutex_unlock(&message_mutex);
}
static errno_t async_req_fast(async_exch_t *exch, sysarg_t imethod,
sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
sysarg_t *r1, sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
if (exch == NULL)
return ENOENT;
ipc_call_t result;
aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,
&result);
errno_t rc;
async_wait_for(aid, &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;
}
static errno_t async_req_slow(async_exch_t *exch, sysarg_t imethod,
sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
sysarg_t *r1, sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
if (exch == NULL)
return ENOENT;
ipc_call_t result;
aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,
&result);
errno_t rc;
async_wait_for(aid, &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;
}
errno_t async_req_0_0(async_exch_t *exch, sysarg_t imethod)
{
return async_req_fast(exch, imethod, 0, 0, 0, 0, NULL, NULL, NULL, NULL,
NULL);
}
errno_t async_req_0_1(async_exch_t *exch, sysarg_t imethod, sysarg_t *r1)
{
return async_req_fast(exch, imethod, 0, 0, 0, 0, r1, NULL, NULL, NULL,
NULL);
}
errno_t async_req_0_2(async_exch_t *exch, sysarg_t imethod, sysarg_t *r1,
sysarg_t *r2)
{
return async_req_fast(exch, imethod, 0, 0, 0, 0, r1, r2, NULL, NULL, NULL);
}
errno_t async_req_0_3(async_exch_t *exch, sysarg_t imethod, sysarg_t *r1,
sysarg_t *r2, sysarg_t *r3)
{
return async_req_fast(exch, imethod, 0, 0, 0, 0, r1, r2, r3, NULL, NULL);
}
errno_t async_req_0_4(async_exch_t *exch, sysarg_t imethod, sysarg_t *r1,
sysarg_t *r2, sysarg_t *r3, sysarg_t *r4)
{
return async_req_fast(exch, imethod, 0, 0, 0, 0, r1, r2, r3, r4, NULL);
}
errno_t async_req_0_5(async_exch_t *exch, sysarg_t imethod, sysarg_t *r1,
sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
return async_req_fast(exch, imethod, 0, 0, 0, 0, r1, r2, r3, r4, r5);
}
errno_t async_req_1_0(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)
{
return async_req_fast(exch, imethod, arg1, 0, 0, 0, NULL, NULL, NULL, NULL,
NULL);
}
errno_t async_req_1_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t *r1)
{
return async_req_fast(exch, imethod, arg1, 0, 0, 0, r1, NULL, NULL, NULL,
NULL);
}
errno_t async_req_1_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t *r1, sysarg_t *r2)
{
return async_req_fast(exch, imethod, arg1, 0, 0, 0, r1, r2, NULL, NULL,
NULL);
}
errno_t async_req_1_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t *r1, sysarg_t *r2, sysarg_t *r3)
{
return async_req_fast(exch, imethod, arg1, 0, 0, 0, r1, r2, r3, NULL,
NULL);
}
errno_t async_req_1_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t *r1, sysarg_t *r2, sysarg_t *r3, sysarg_t *r4)
{
return async_req_fast(exch, imethod, arg1, 0, 0, 0, r1, r2, r3, r4, NULL);
}
errno_t async_req_1_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t *r1, sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
return async_req_fast(exch, imethod, arg1, 0, 0, 0, r1, r2, r3, r4, r5);
}
errno_t async_req_2_0(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2)
{
return async_req_fast(exch, imethod, arg1, arg2, 0, 0, NULL, NULL, NULL,
NULL, NULL);
}
errno_t async_req_2_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t *r1)
{
return async_req_fast(exch, imethod, arg1, arg2, 0, 0, r1, NULL, NULL,
NULL, NULL);
}
errno_t async_req_2_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t *r1, sysarg_t *r2)
{
return async_req_fast(exch, imethod, arg1, arg2, 0, 0, r1, r2, NULL,
NULL, NULL);
}
errno_t async_req_2_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t *r1, sysarg_t *r2, sysarg_t *r3)
{
return async_req_fast(exch, imethod, arg1, arg2, 0, 0, r1, r2, r3, NULL,
NULL);
}
errno_t async_req_2_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t *r1, sysarg_t *r2, sysarg_t *r3, sysarg_t *r4)
{
return async_req_fast(exch, imethod, arg1, arg2, 0, 0, r1, r2, r3, r4,
NULL);
}
errno_t async_req_2_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t *r1, sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
return async_req_fast(exch, imethod, arg1, arg2, 0, 0, r1, r2, r3, r4, r5);
}
errno_t async_req_3_0(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, 0, NULL, NULL, NULL,
NULL, NULL);
}
errno_t async_req_3_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t *r1)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, 0, r1, NULL, NULL,
NULL, NULL);
}
errno_t async_req_3_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t *r1, sysarg_t *r2)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, 0, r1, r2, NULL,
NULL, NULL);
}
errno_t async_req_3_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t *r1, sysarg_t *r2, sysarg_t *r3)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, 0, r1, r2, r3, NULL,
NULL);
}
errno_t async_req_3_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t *r1, sysarg_t *r2, sysarg_t *r3,
sysarg_t *r4)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, 0, r1, r2, r3, r4,
NULL);
}
errno_t async_req_3_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t *r1, sysarg_t *r2, sysarg_t *r3,
sysarg_t *r4, sysarg_t *r5)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, 0, r1, r2, r3, r4,
r5);
}
errno_t async_req_4_0(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
NULL, NULL, NULL);
}
errno_t async_req_4_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, arg4, r1, NULL,
NULL, NULL, NULL);
}
errno_t async_req_4_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, arg4, r1, r2, NULL,
NULL, NULL);
}
errno_t async_req_4_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
sysarg_t *r3)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, arg4, r1, r2, r3,
NULL, NULL);
}
errno_t async_req_4_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
sysarg_t *r3, sysarg_t *r4)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, arg4, r1, r2, r3,
r4, NULL);
}
errno_t async_req_4_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
return async_req_fast(exch, imethod, arg1, arg2, arg3, arg4, r1, r2, r3,
r4, r5);
}
errno_t async_req_5_0(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
{
return async_req_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
NULL, NULL, NULL, NULL);
}
errno_t async_req_5_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1)
{
return async_req_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5, r1,
NULL, NULL, NULL, NULL);
}
errno_t async_req_5_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
sysarg_t *r2)
{
return async_req_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5, r1, r2,
NULL, NULL, NULL);
}
errno_t async_req_5_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
sysarg_t *r2, sysarg_t *r3)
{
return async_req_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5, r1, r2,
r3, NULL, NULL);
}
errno_t async_req_5_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
sysarg_t *r2, sysarg_t *r3, sysarg_t *r4)
{
return async_req_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5, r1, r2,
r3, r4, NULL);
}
errno_t async_req_5_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
{
return async_req_slow(exch, imethod, arg1, arg2, arg3, arg4, arg5, r1, r2,
r3, r4, r5);
}
void async_msg_0(async_exch_t *exch, sysarg_t imethod)
{
if (exch != NULL)
ipc_call_async_0(exch->phone, imethod, NULL);
}
void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)
{
if (exch != NULL)
ipc_call_async_1(exch->phone, imethod, arg1, NULL);
}
void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2)
{
if (exch != NULL)
ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL);
}
void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3)
{
if (exch != NULL)
ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL);
}
void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
{
if (exch != NULL)
ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,
NULL);
}
void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
{
if (exch != NULL)
ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,
arg5, NULL);
}
static errno_t async_connect_me_to_internal(cap_phone_handle_t phone,
iface_t iface, sysarg_t arg2, sysarg_t arg3, sysarg_t flags,
cap_phone_handle_t *out_phone)
{
ipc_call_t result;
*out_phone = CAP_NIL;
amsg_t *msg = amsg_create();
if (!msg)
return ENOENT;
msg->dataptr = &result;
errno_t rc = ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO,
(sysarg_t) iface, arg2, arg3, flags, msg);
if (rc != EOK) {
msg->retval = rc;
msg->done = true;
}
async_wait_for((aid_t) msg, &rc);
if (rc != EOK)
return rc;
*out_phone = (cap_phone_handle_t) ipc_get_arg5(&result);
return EOK;
}
async_sess_t *async_connect_me_to(async_exch_t *exch, iface_t iface,
sysarg_t arg2, sysarg_t arg3, errno_t *rc)
{
if (exch == NULL) {
if (rc != NULL)
*rc = ENOENT;
return NULL;
}
async_sess_t *sess = calloc(1, sizeof(async_sess_t));
if (sess == NULL) {
if (rc != NULL)
*rc = ENOMEM;
return NULL;
}
cap_phone_handle_t phone;
errno_t ret = async_connect_me_to_internal(exch->phone, iface, arg2,
arg3, 0, &phone);
if (ret != EOK) {
if (rc != NULL)
*rc = ret;
free(sess);
return NULL;
}
sess->iface = iface;
sess->phone = phone;
sess->arg1 = iface;
sess->arg2 = arg2;
sess->arg3 = arg3;
fibril_mutex_initialize(&sess->remote_state_mtx);
list_initialize(&sess->exch_list);
fibril_mutex_initialize(&sess->mutex);
return sess;
}
void async_sess_args_set(async_sess_t *sess, iface_t iface, sysarg_t arg2,
sysarg_t arg3)
{
sess->arg1 = iface;
sess->arg2 = arg2;
sess->arg3 = arg3;
}
async_sess_t *async_connect_me_to_blocking(async_exch_t *exch, iface_t iface,
sysarg_t arg2, sysarg_t arg3, errno_t *rc)
{
if (exch == NULL) {
if (rc != NULL)
*rc = ENOENT;
return NULL;
}
async_sess_t *sess = calloc(1, sizeof(async_sess_t));
if (sess == NULL) {
if (rc != NULL)
*rc = ENOMEM;
return NULL;
}
cap_phone_handle_t phone;
errno_t ret = async_connect_me_to_internal(exch->phone, iface, arg2,
arg3, IPC_FLAG_BLOCKING, &phone);
if (ret != EOK) {
if (rc != NULL)
*rc = ret;
free(sess);
return NULL;
}
sess->iface = iface;
sess->phone = phone;
sess->arg1 = iface;
sess->arg2 = arg2;
sess->arg3 = arg3;
fibril_mutex_initialize(&sess->remote_state_mtx);
list_initialize(&sess->exch_list);
fibril_mutex_initialize(&sess->mutex);
return sess;
}
async_sess_t *async_connect_kbox(task_id_t id, errno_t *rc)
{
async_sess_t *sess = calloc(1, sizeof(async_sess_t));
if (sess == NULL) {
if (rc != NULL)
*rc = ENOMEM;
return NULL;
}
cap_phone_handle_t phone;
errno_t ret = ipc_connect_kbox(id, &phone);
if (ret != EOK) {
if (rc != NULL)
*rc = ret;
free(sess);
return NULL;
}
sess->iface = 0;
sess->mgmt = EXCHANGE_ATOMIC;
sess->phone = phone;
fibril_mutex_initialize(&sess->remote_state_mtx);
list_initialize(&sess->exch_list);
fibril_mutex_initialize(&sess->mutex);
return sess;
}
static void async_hangup_internal(cap_phone_handle_t phone)
{
errno_t rc;
rc = ipc_hangup(phone);
assert(rc == EOK);
(void) rc;
}
void async_hangup(async_sess_t *sess)
{
async_exch_t *exch;
assert(sess);
fibril_mutex_lock(&async_sess_mutex);
assert(sess->exchanges == 0);
async_hangup_internal(sess->phone);
while (!list_empty(&sess->exch_list)) {
exch = (async_exch_t *)
list_get_instance(list_first(&sess->exch_list),
async_exch_t, sess_link);
list_remove(&exch->sess_link);
list_remove(&exch->global_link);
if (sess->mgmt != EXCHANGE_ATOMIC &&
sess->mgmt != EXCHANGE_SERIALIZE)
async_hangup_internal(exch->phone);
free(exch);
}
free(sess);
fibril_mutex_unlock(&async_sess_mutex);
}
async_exch_t *async_exchange_begin(async_sess_t *sess)
{
if (sess == NULL)
return NULL;
exch_mgmt_t mgmt = sess->mgmt;
if (sess->iface != 0)
mgmt = sess->iface & IFACE_EXCHANGE_MASK;
async_exch_t *exch = NULL;
fibril_mutex_lock(&async_sess_mutex);
if (!list_empty(&sess->exch_list)) {
exch = (async_exch_t *)
list_get_instance(list_first(&sess->exch_list),
async_exch_t, sess_link);
list_remove(&exch->sess_link);
list_remove(&exch->global_link);
} else {
if ((mgmt == EXCHANGE_ATOMIC) ||
(mgmt == EXCHANGE_SERIALIZE)) {
exch = (async_exch_t *) malloc(sizeof(async_exch_t));
if (exch != NULL) {
link_initialize(&exch->sess_link);
link_initialize(&exch->global_link);
exch->sess = sess;
exch->phone = sess->phone;
}
} else if (mgmt == EXCHANGE_PARALLEL) {
cap_phone_handle_t phone;
errno_t rc;
retry:
rc = async_connect_me_to_internal(sess->phone, sess->arg1,
sess->arg2, sess->arg3, 0, &phone);
if (rc == EOK) {
exch = (async_exch_t *) malloc(sizeof(async_exch_t));
if (exch != NULL) {
link_initialize(&exch->sess_link);
link_initialize(&exch->global_link);
exch->sess = sess;
exch->phone = phone;
} else
async_hangup_internal(phone);
} else if (!list_empty(&inactive_exch_list)) {
exch = (async_exch_t *)
list_get_instance(list_first(&inactive_exch_list),
async_exch_t, global_link);
list_remove(&exch->sess_link);
list_remove(&exch->global_link);
async_hangup_internal(exch->phone);
free(exch);
goto retry;
} else {
fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
goto retry;
}
}
}
if (exch != NULL)
sess->exchanges++;
fibril_mutex_unlock(&async_sess_mutex);
if (exch != NULL && mgmt == EXCHANGE_SERIALIZE)
fibril_mutex_lock(&sess->mutex);
return exch;
}
void async_exchange_end(async_exch_t *exch)
{
if (exch == NULL)
return;
async_sess_t *sess = exch->sess;
assert(sess != NULL);
exch_mgmt_t mgmt = sess->mgmt;
if (sess->iface != 0)
mgmt = sess->iface & IFACE_EXCHANGE_MASK;
if (mgmt == EXCHANGE_SERIALIZE)
fibril_mutex_unlock(&sess->mutex);
fibril_mutex_lock(&async_sess_mutex);
sess->exchanges--;
list_append(&exch->sess_link, &sess->exch_list);
list_append(&exch->global_link, &inactive_exch_list);
fibril_condvar_signal(&avail_phone_cv);
fibril_mutex_unlock(&async_sess_mutex);
}
static errno_t async_share_in_start(async_exch_t *exch, size_t size,
sysarg_t arg, unsigned int *flags, void **dst)
{
if (exch == NULL)
return ENOENT;
sysarg_t _flags = 0;
sysarg_t _dst = (sysarg_t) -1;
errno_t res = async_req_3_5(exch, IPC_M_SHARE_IN, (sysarg_t) size,
(sysarg_t) __progsymbols.end, arg, NULL, &_flags, NULL, NULL,
&_dst);
if (flags)
*flags = (unsigned int) _flags;
*dst = (void *) _dst;
return res;
}
errno_t async_share_in_start_0_0(async_exch_t *exch, size_t size, void **dst)
{
return async_share_in_start(exch, size, 0, NULL, dst);
}
errno_t async_share_in_start_0_1(async_exch_t *exch, size_t size,
unsigned int *flags, void **dst)
{
return async_share_in_start(exch, size, 0, flags, dst);
}
errno_t async_share_in_start_1_0(async_exch_t *exch, size_t size, sysarg_t arg,
void **dst)
{
return async_share_in_start(exch, size, arg, NULL, dst);
}
errno_t async_share_in_start_1_1(async_exch_t *exch, size_t size, sysarg_t arg,
unsigned int *flags, void **dst)
{
return async_share_in_start(exch, size, arg, flags, dst);
}
errno_t async_share_out_start(async_exch_t *exch, void *src, unsigned int flags)
{
if (exch == NULL)
return ENOENT;
return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
(sysarg_t) flags);
}
aid_t async_data_read(async_exch_t *exch, void *dst, size_t size,
ipc_call_t *dataptr)
{
return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst,
(sysarg_t) size, dataptr);
}
errno_t async_data_read_start(async_exch_t *exch, void *dst, size_t size)
{
if (exch == NULL)
return ENOENT;
return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst,
(sysarg_t) size);
}
errno_t async_data_write_start(async_exch_t *exch, const void *src, size_t size)
{
if (exch == NULL)
return ENOENT;
return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src,
(sysarg_t) size);
}
errno_t async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
sysarg_t arg3, async_exch_t *other_exch)
{
return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE,
arg1, arg2, arg3, 0, cap_handle_raw(other_exch->phone));
}
void *async_remote_state_acquire(async_sess_t *sess)
{
fibril_mutex_lock(&sess->remote_state_mtx);
return sess->remote_state_data;
}
void async_remote_state_update(async_sess_t *sess, void *state)
{
assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
sess->remote_state_data = state;
}
void async_remote_state_release(async_sess_t *sess)
{
assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
fibril_mutex_unlock(&sess->remote_state_mtx);
}
void async_remote_state_release_exchange(async_exch_t *exch)
{
if (exch == NULL)
return;
async_sess_t *sess = exch->sess;
assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
async_exchange_end(exch);
fibril_mutex_unlock(&sess->remote_state_mtx);
}
void *async_as_area_create(void *base, size_t size, unsigned int flags,
async_sess_t *pager, sysarg_t id1, sysarg_t id2, sysarg_t id3)
{
as_area_pager_info_t pager_info = {
.pager = pager->phone,
.id1 = id1,
.id2 = id2,
.id3 = id3
};
return as_area_create(base, size, flags, &pager_info);
}
HelenOS homepage, sources at GitHub