Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async.c

    r8e80d3f r79ae36dd  
    4040 * programming.
    4141 *
    42  * You should be able to write very simple multithreaded programs, the async
    43  * framework will automatically take care of most synchronization problems.
     42 * You should be able to write very simple multithreaded programs. The async
     43 * framework will automatically take care of most of the synchronization
     44 * problems.
    4445 *
    4546 * Example of use (pseudo C):
     
    5354 *   int fibril1(void *arg)
    5455 *   {
    55  *     conn = async_connect_me_to();
    56  *     c1 = async_send(conn);
    57  *     c2 = async_send(conn);
     56 *     conn = async_connect_me_to(...);
     57 *
     58 *     exch = async_exchange_begin(conn);
     59 *     c1 = async_send(exch);
     60 *     async_exchange_end(exch);
     61 *
     62 *     exch = async_exchange_begin(conn);
     63 *     c2 = async_send(exch);
     64 *     async_exchange_end(exch);
     65 *
    5866 *     async_wait_for(c1);
    5967 *     async_wait_for(c2);
     
    94102#include <futex.h>
    95103#include <fibril.h>
    96 #include <stdio.h>
    97104#include <adt/hash_table.h>
    98105#include <adt/list.h>
     
    102109#include <arch/barrier.h>
    103110#include <bool.h>
     111#include <malloc.h>
     112#include <mem.h>
     113#include <stdlib.h>
    104114#include "private/async.h"
    105115
     116#define CLIENT_HASH_TABLE_BUCKETS  32
     117#define CONN_HASH_TABLE_BUCKETS    32
     118
     119/** Async framework global futex */
    106120atomic_t async_futex = FUTEX_INITIALIZER;
    107121
     
    109123atomic_t threads_in_ipc_wait = { 0 };
    110124
    111 typedef struct {
    112         awaiter_t wdata;
    113        
    114         /** If reply was received. */
    115         bool done;
    116        
    117         /** Pointer to where the answer data is stored. */
    118         ipc_call_t *dataptr;
    119        
    120         sysarg_t retval;
    121 } amsg_t;
    122 
    123 /**
    124  * Structures of this type are used to group information about
    125  * a call and about a message queue link.
    126  */
     125/** Naming service session */
     126async_sess_t *session_ns;
     127
     128/** Call data */
    127129typedef struct {
    128130        link_t link;
     131       
    129132        ipc_callid_t callid;
    130133        ipc_call_t call;
    131134} msg_t;
    132135
     136/* Client connection data */
    133137typedef struct {
     138        link_t link;
     139       
    134140        sysarg_t in_task_hash;
    135         link_t link;
    136         int refcnt;
     141        atomic_t refcnt;
    137142        void *data;
    138143} client_t;
    139144
     145/* Server connection data */
    140146typedef struct {
    141147        awaiter_t wdata;
     
    146152        /** Incoming client task hash. */
    147153        sysarg_t in_task_hash;
     154       
    148155        /** Incoming phone hash. */
    149156        sysarg_t in_phone_hash;
     
    168175
    169176/** Identifier of the incoming connection handled by the current fibril. */
    170 static fibril_local connection_t *FIBRIL_connection;
     177static fibril_local connection_t *fibril_connection;
    171178
    172179static void *default_client_data_constructor(void)
     
    194201}
    195202
    196 void *async_client_data_get(void)
    197 {
    198         assert(FIBRIL_connection);
    199         return FIBRIL_connection->client->data;
     203void *async_get_client_data(void)
     204{
     205        assert(fibril_connection);
     206        return fibril_connection->client->data;
    200207}
    201208
     
    213220}
    214221
    215 /**
    216  * Pointer to a fibril function that will be used to handle connections.
    217  */
    218 static async_client_conn_t client_connection = default_client_connection;
    219 
    220222/** Default fibril function that gets called to handle interrupt notifications.
    221223 *
     
    230232}
    231233
    232 /**
    233  * Pointer to a fibril function that will be used to handle interrupt
    234  * notifications.
    235  */
     234static async_client_conn_t client_connection = default_client_connection;
    236235static async_client_conn_t interrupt_received = default_interrupt_received;
     236
     237/** Setter for client_connection function pointer.
     238 *
     239 * @param conn Function that will implement a new connection fibril.
     240 *
     241 */
     242void async_set_client_connection(async_client_conn_t conn)
     243{
     244        client_connection = conn;
     245}
     246
     247/** Setter for interrupt_received function pointer.
     248 *
     249 * @param intr Function that will implement a new interrupt
     250 *             notification fibril.
     251 */
     252void async_set_interrupt_received(async_client_conn_t intr)
     253{
     254        interrupt_received = intr;
     255}
     256
     257/** Mutex protecting inactive_exch_list and avail_phone_cv.
     258 *
     259 */
     260static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);
     261
     262/** List of all currently inactive exchanges.
     263 *
     264 */
     265static LIST_INITIALIZE(inactive_exch_list);
     266
     267/** Condition variable to wait for a phone to become available.
     268 *
     269 */
     270static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
    237271
    238272static hash_table_t client_hash_table;
     
    240274static LIST_INITIALIZE(timeout_list);
    241275
    242 #define CLIENT_HASH_TABLE_BUCKETS  32
    243 #define CONN_HASH_TABLE_BUCKETS    32
    244 
    245276static hash_index_t client_hash(unsigned long key[])
    246277{
    247278        assert(key);
     279       
    248280        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
    249281}
     
    251283static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
    252284{
     285        assert(key);
     286        assert(item);
     287       
    253288        client_t *client = hash_table_get_instance(item, client_t, link);
    254289        return (key[0] == client->in_task_hash);
     
    276311{
    277312        assert(key);
     313       
    278314        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
    279315}
     
    290326static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
    291327{
     328        assert(key);
     329        assert(item);
     330       
    292331        connection_t *conn = hash_table_get_instance(item, connection_t, link);
    293332        return (key[0] == conn->in_phone_hash);
     
    312351void async_insert_timeout(awaiter_t *wd)
    313352{
     353        assert(wd);
     354       
    314355        wd->to_event.occurred = false;
    315356        wd->to_event.inlist = true;
     
    344385static bool route_call(ipc_callid_t callid, ipc_call_t *call)
    345386{
     387        assert(call);
     388       
    346389        futex_down(&async_futex);
    347390       
     
    398441static int notification_fibril(void *arg)
    399442{
     443        assert(arg);
     444       
    400445        msg_t *msg = (msg_t *) arg;
    401446        interrupt_received(msg->callid, &msg->call);
     
    418463static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
    419464{
     465        assert(call);
     466       
    420467        futex_down(&async_futex);
    421468       
     
    456503ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
    457504{
    458         assert(FIBRIL_connection);
     505        assert(call);
     506        assert(fibril_connection);
    459507       
    460508        /* Why doing this?
    461          * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.
     509         * GCC 4.1.0 coughs on fibril_connection-> dereference.
    462510         * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
    463511         *           I would never expect to find so many errors in
    464512         *           a compiler.
    465513         */
    466         connection_t *conn = FIBRIL_connection;
     514        connection_t *conn = fibril_connection;
    467515       
    468516        futex_down(&async_futex);
     
    539587static int connection_fibril(void *arg)
    540588{
     589        assert(arg);
     590       
    541591        /*
    542592         * Setup fibril-local connection pointer.
    543593         */
    544         FIBRIL_connection = (connection_t *) arg;
     594        fibril_connection = (connection_t *) arg;
    545595       
    546596        futex_down(&async_futex);
     
    552602         */
    553603       
    554         unsigned long key = FIBRIL_connection->in_task_hash;
     604        unsigned long key = fibril_connection->in_task_hash;
    555605        link_t *lnk = hash_table_find(&client_hash_table, &key);
    556606       
     
    559609        if (lnk) {
    560610                client = hash_table_get_instance(lnk, client_t, link);
    561                 client->refcnt++;
     611                atomic_inc(&client->refcnt);
    562612        } else {
    563613                client = malloc(sizeof(client_t));
    564614                if (!client) {
    565                         ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
     615                        ipc_answer_0(fibril_connection->callid, ENOMEM);
    566616                        futex_up(&async_futex);
    567617                        return 0;
    568618                }
    569619               
    570                 client->in_task_hash = FIBRIL_connection->in_task_hash;
    571                
    572                 async_serialize_start();
     620                client->in_task_hash = fibril_connection->in_task_hash;
    573621                client->data = async_client_data_create();
    574                 async_serialize_end();
    575                
    576                 client->refcnt = 1;
     622               
     623                atomic_set(&client->refcnt, 1);
    577624                hash_table_insert(&client_hash_table, &key, &client->link);
    578625        }
     
    580627        futex_up(&async_futex);
    581628       
    582         FIBRIL_connection->client = client;
     629        fibril_connection->client = client;
    583630       
    584631        /*
    585632         * Call the connection handler function.
    586633         */
    587         FIBRIL_connection->cfibril(FIBRIL_connection->callid,
    588             &FIBRIL_connection->call);
     634        fibril_connection->cfibril(fibril_connection->callid,
     635            &fibril_connection->call);
    589636       
    590637        /*
     
    595642        futex_down(&async_futex);
    596643       
    597         if (--client->refcnt == 0) {
     644        if (atomic_predec(&client->refcnt) == 0) {
    598645                hash_table_remove(&client_hash_table, &key, 1);
    599646                destroy = true;
     
    614661         */
    615662        futex_down(&async_futex);
    616         key = FIBRIL_connection->in_phone_hash;
     663        key = fibril_connection->in_phone_hash;
    617664        hash_table_remove(&conn_hash_table, &key, 1);
    618665        futex_up(&async_futex);
     
    621668         * Answer all remaining messages with EHANGUP.
    622669         */
    623         while (!list_empty(&FIBRIL_connection->msg_queue)) {
     670        while (!list_empty(&fibril_connection->msg_queue)) {
    624671                msg_t *msg =
    625                     list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
     672                    list_get_instance(fibril_connection->msg_queue.next, msg_t,
    626673                    link);
    627674               
     
    635682         * i.e. IPC_M_PHONE_HUNGUP.
    636683         */
    637         if (FIBRIL_connection->close_callid)
    638                 ipc_answer_0(FIBRIL_connection->close_callid, EOK);
    639        
    640         free(FIBRIL_connection);
     684        if (fibril_connection->close_callid)
     685                ipc_answer_0(fibril_connection->close_callid, EOK);
     686       
     687        free(fibril_connection);
    641688        return 0;
    642689}
     
    644691/** Create a new fibril for a new connection.
    645692 *
    646  * Create new fibril for connection, fill in connection structures and inserts
     693 * Create new fibril for connection, fill in connection structures and insert
    647694 * it into the hash table, so that later we can easily do routing of messages to
    648695 * particular fibrils.
     
    663710fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
    664711    ipc_callid_t callid, ipc_call_t *call,
    665     void (*cfibril)(ipc_callid_t, ipc_call_t *))
     712    async_client_conn_t cfibril)
    666713{
    667714        connection_t *conn = malloc(sizeof(*conn));
     
    719766static void handle_call(ipc_callid_t callid, ipc_call_t *call)
    720767{
     768        assert(call);
     769       
    721770        /* Unrouted call - take some default action */
    722771        if ((callid & IPC_CALLID_NOTIFICATION)) {
     
    876925void __async_init(void)
    877926{
    878         if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
    879             &client_hash_table_ops))
     927        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
     928            1, &client_hash_table_ops))
    880929                abort();
    881930       
    882         if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
    883             &conn_hash_table_ops))
     931        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
     932            1, &conn_hash_table_ops))
    884933                abort();
     934       
     935        session_ns = (async_sess_t *) malloc(sizeof(async_sess_t));
     936        if (session_ns == NULL)
     937                abort();
     938       
     939        session_ns->mgmt = EXCHANGE_ATOMIC;
     940        session_ns->phone = PHONE_NS;
     941        session_ns->arg1 = 0;
     942        session_ns->arg2 = 0;
     943        session_ns->arg3 = 0;
     944       
     945        list_initialize(&session_ns->exch_list);
     946        fibril_mutex_initialize(&session_ns->mutex);
     947        atomic_set(&session_ns->refcnt, 0);
    885948}
    886949
     
    897960 *
    898961 */
    899 static void reply_received(void *arg, int retval, ipc_call_t *data)
    900 {
     962void reply_received(void *arg, int retval, ipc_call_t *data)
     963{
     964        assert(arg);
     965       
    901966        futex_down(&async_futex);
    902967       
     
    928993 * completion.
    929994 *
    930  * @param phoneid Handle of the phone that will be used for the send.
    931  * @param method  Service-defined method.
     995 * @param exch    Exchange for sending the message.
     996 * @param imethod Service-defined interface and method.
    932997 * @param arg1    Service-defined payload argument.
    933998 * @param arg2    Service-defined payload argument.
     
    9401005 *
    9411006 */
    942 aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
     1007aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    9431008    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    9441009{
     1010        if (exch == NULL)
     1011                return 0;
     1012       
    9451013        amsg_t *msg = malloc(sizeof(amsg_t));
    946        
    947         if (!msg)
     1014        if (msg == NULL)
    9481015                return 0;
    9491016       
     
    9591026        msg->wdata.active = true;
    9601027       
    961         ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
     1028        ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,
    9621029            reply_received, true);
    9631030       
     
    9701037 * completion.
    9711038 *
    972  * @param phoneid Handle of the phone that will be used for the send.
    973  * @param method  Service-defined method.
     1039 * @param exch    Exchange for sending the message.
     1040 * @param imethod Service-defined interface and method.
    9741041 * @param arg1    Service-defined payload argument.
    9751042 * @param arg2    Service-defined payload argument.
     
    9831050 *
    9841051 */
    985 aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
     1052aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    9861053    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    9871054    ipc_call_t *dataptr)
    9881055{
     1056        if (exch == NULL)
     1057                return 0;
     1058       
    9891059        amsg_t *msg = malloc(sizeof(amsg_t));
    9901060       
    991         if (!msg)
     1061        if (msg == NULL)
    9921062                return 0;
    9931063       
     
    10031073        msg->wdata.active = true;
    10041074       
    1005         ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
    1006             reply_received, true);
     1075        ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,
     1076            msg, reply_received, true);
    10071077       
    10081078        return (aid_t) msg;
     
    10181088void async_wait_for(aid_t amsgid, sysarg_t *retval)
    10191089{
     1090        assert(amsgid);
     1091       
    10201092        amsg_t *msg = (amsg_t *) amsgid;
    10211093       
     
    10541126int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout)
    10551127{
     1128        assert(amsgid);
     1129       
    10561130        amsg_t *msg = (amsg_t *) amsgid;
    10571131       
     
    11221196}
    11231197
    1124 /** Setter for client_connection function pointer.
    1125  *
    1126  * @param conn Function that will implement a new connection fibril.
    1127  *
    1128  */
    1129 void async_set_client_connection(async_client_conn_t conn)
    1130 {
    1131         client_connection = conn;
    1132 }
    1133 
    1134 /** Setter for interrupt_received function pointer.
    1135  *
    1136  * @param intr Function that will implement a new interrupt
    1137  *             notification fibril.
    1138  */
    1139 void async_set_interrupt_received(async_client_conn_t intr)
    1140 {
    1141         interrupt_received = intr;
    1142 }
    1143 
    11441198/** Pseudo-synchronous message sending - fast version.
    11451199 *
     
    11491203 * transferring more arguments, see the slower async_req_slow().
    11501204 *
    1151  * @param phoneid Hash of the phone through which to make the call.
    1152  * @param method  Method of the call.
     1205 * @param exch    Exchange for sending the message.
     1206 * @param imethod Interface and method of the call.
    11531207 * @param arg1    Service-defined payload argument.
    11541208 * @param arg2    Service-defined payload argument.
     
    11641218 *
    11651219 */
    1166 sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
     1220sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    11671221    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
    11681222    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
    11691223{
     1224        if (exch == NULL)
     1225                return ENOENT;
     1226       
    11701227        ipc_call_t result;
    1171         aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
     1228        aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,
    11721229            &result);
    11731230       
    11741231        sysarg_t rc;
    1175         async_wait_for(eid, &rc);
     1232        async_wait_for(aid, &rc);
    11761233       
    11771234        if (r1)
     
    11971254 * Send message asynchronously and return only after the reply arrives.
    11981255 *
    1199  * @param phoneid Hash of the phone through which to make the call.
    1200  * @param method  Method of the call.
     1256 * @param exch    Exchange for sending the message.
     1257 * @param imethod Interface and method of the call.
    12011258 * @param arg1    Service-defined payload argument.
    12021259 * @param arg2    Service-defined payload argument.
     
    12131270 *
    12141271 */
    1215 sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
     1272sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    12161273    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
    12171274    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
    12181275{
     1276        if (exch == NULL)
     1277                return ENOENT;
     1278       
    12191279        ipc_call_t result;
    1220         aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
     1280        aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,
    12211281            &result);
    12221282       
    12231283        sysarg_t rc;
    1224         async_wait_for(eid, &rc);
     1284        async_wait_for(aid, &rc);
    12251285       
    12261286        if (r1)
     
    12421302}
    12431303
    1244 void async_msg_0(int phone, sysarg_t imethod)
    1245 {
    1246         ipc_call_async_0(phone, imethod, NULL, NULL, true);
    1247 }
    1248 
    1249 void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
    1250 {
    1251         ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
    1252 }
    1253 
    1254 void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
    1255 {
    1256         ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
    1257 }
    1258 
    1259 void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
    1260     sysarg_t arg3)
    1261 {
    1262         ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
    1263 }
    1264 
    1265 void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
    1266     sysarg_t arg3, sysarg_t arg4)
    1267 {
    1268         ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
    1269             true);
    1270 }
    1271 
    1272 void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
    1273     sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
    1274 {
    1275         ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
    1276             NULL, true);
     1304void async_msg_0(async_exch_t *exch, sysarg_t imethod)
     1305{
     1306        if (exch != NULL)
     1307                ipc_call_async_0(exch->phone, imethod, NULL, NULL, true);
     1308}
     1309
     1310void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)
     1311{
     1312        if (exch != NULL)
     1313                ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true);
     1314}
     1315
     1316void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1317    sysarg_t arg2)
     1318{
     1319        if (exch != NULL)
     1320                ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL,
     1321                    true);
     1322}
     1323
     1324void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1325    sysarg_t arg2, sysarg_t arg3)
     1326{
     1327        if (exch != NULL)
     1328                ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL,
     1329                    NULL, true);
     1330}
     1331
     1332void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1333    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
     1334{
     1335        if (exch != NULL)
     1336                ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,
     1337                    NULL, NULL, true);
     1338}
     1339
     1340void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1341    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
     1342{
     1343        if (exch != NULL)
     1344                ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,
     1345                    arg5, NULL, NULL, true);
    12771346}
    12781347
     
    13111380}
    13121381
    1313 int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
    1314     sysarg_t arg1, sysarg_t arg2, unsigned int mode)
    1315 {
    1316         return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
    1317 }
    1318 
    1319 int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
    1320     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    1321     unsigned int mode)
    1322 {
    1323         return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
    1324             arg5, mode);
     1382int async_forward_fast(ipc_callid_t callid, async_exch_t *exch,
     1383    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
     1384{
     1385        if (exch == NULL)
     1386                return ENOENT;
     1387       
     1388        return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode);
     1389}
     1390
     1391int async_forward_slow(ipc_callid_t callid, async_exch_t *exch,
     1392    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
     1393    sysarg_t arg4, sysarg_t arg5, unsigned int mode)
     1394{
     1395        if (exch == NULL)
     1396                return ENOENT;
     1397       
     1398        return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3,
     1399            arg4, arg5, mode);
    13251400}
    13261401
     
    13291404 * Ask through phone for a new connection to some service.
    13301405 *
    1331  * @param phone           Phone handle used for contacting the other side.
     1406 * @param exch            Exchange for sending the message.
    13321407 * @param arg1            User defined argument.
    13331408 * @param arg2            User defined argument.
     
    13351410 * @param client_receiver Connection handing routine.
    13361411 *
    1337  * @return New phone handle on success or a negative error code.
    1338  *
    1339  */
    1340 int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
     1412 * @return Zero on success or a negative error code.
     1413 *
     1414 */
     1415int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
    13411416    sysarg_t arg3, async_client_conn_t client_receiver)
    13421417{
     1418        if (exch == NULL)
     1419                return ENOENT;
     1420       
    13431421        sysarg_t task_hash;
    13441422        sysarg_t phone_hash;
    1345         int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
     1423        int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    13461424            NULL, NULL, NULL, &task_hash, &phone_hash);
    13471425        if (rc != EOK)
     
    13551433}
    13561434
    1357 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
    1358  *
    1359  * Ask through phone for a new connection to some service.
    1360  *
    1361  * @param phone Phone handle used for contacting the other side.
    1362  * @param arg1  User defined argument.
    1363  * @param arg2  User defined argument.
    1364  * @param arg3  User defined argument.
    1365  *
    1366  * @return New phone handle on success or a negative error code.
    1367  *
    1368  */
    1369 int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
    1370     sysarg_t arg3)
    1371 {
    1372         sysarg_t newphid;
    1373         int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
    1374             NULL, NULL, NULL, NULL, &newphid);
     1435/** Wrapper for making IPC_M_CONNECT_ME calls using the async framework.
     1436 *
     1437 * Ask through for a cloned connection to some service.
     1438 *
     1439 * @param mgmt Exchange management style.
     1440 * @param exch Exchange for sending the message.
     1441 *
     1442 * @return New session on success or NULL on error.
     1443 *
     1444 */
     1445async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch)
     1446{
     1447        if (exch == NULL) {
     1448                errno = ENOENT;
     1449                return NULL;
     1450        }
     1451       
     1452        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
     1453        if (sess == NULL) {
     1454                errno = ENOMEM;
     1455                return NULL;
     1456        }
     1457       
     1458        ipc_call_t result;
     1459       
     1460        amsg_t *msg = malloc(sizeof(amsg_t));
     1461        if (msg == NULL) {
     1462                free(sess);
     1463                errno = ENOMEM;
     1464                return NULL;
     1465        }
     1466       
     1467        msg->done = false;
     1468        msg->dataptr = &result;
     1469       
     1470        msg->wdata.to_event.inlist = false;
     1471       
     1472        /*
     1473         * We may sleep in the next method,
     1474         * but it will use its own means
     1475         */
     1476        msg->wdata.active = true;
     1477       
     1478        ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg,
     1479            reply_received, true);
     1480       
     1481        sysarg_t rc;
     1482        async_wait_for((aid_t) msg, &rc);
     1483       
     1484        if (rc != EOK) {
     1485                errno = rc;
     1486                free(sess);
     1487                return NULL;
     1488        }
     1489       
     1490        int phone = (int) IPC_GET_ARG5(result);
     1491       
     1492        if (phone < 0) {
     1493                errno = phone;
     1494                free(sess);
     1495                return NULL;
     1496        }
     1497       
     1498        sess->mgmt = mgmt;
     1499        sess->phone = phone;
     1500        sess->arg1 = 0;
     1501        sess->arg2 = 0;
     1502        sess->arg3 = 0;
     1503       
     1504        list_initialize(&sess->exch_list);
     1505        fibril_mutex_initialize(&sess->mutex);
     1506        atomic_set(&sess->refcnt, 0);
     1507       
     1508        return sess;
     1509}
     1510
     1511static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2,
     1512    sysarg_t arg3, sysarg_t arg4)
     1513{
     1514        ipc_call_t result;
     1515       
     1516        amsg_t *msg = malloc(sizeof(amsg_t));
     1517        if (msg == NULL)
     1518                return ENOENT;
     1519       
     1520        msg->done = false;
     1521        msg->dataptr = &result;
     1522       
     1523        msg->wdata.to_event.inlist = false;
     1524       
     1525        /*
     1526         * We may sleep in the next method,
     1527         * but it will use its own means
     1528         */
     1529        msg->wdata.active = true;
     1530       
     1531        ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4,
     1532            msg, reply_received, true);
     1533       
     1534        sysarg_t rc;
     1535        async_wait_for((aid_t) msg, &rc);
    13751536       
    13761537        if (rc != EOK)
    13771538                return rc;
    13781539       
    1379         return newphid;
     1540        return (int) IPC_GET_ARG5(result);
     1541}
     1542
     1543/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
     1544 *
     1545 * Ask through for a new connection to some service.
     1546 *
     1547 * @param mgmt Exchange management style.
     1548 * @param exch Exchange for sending the message.
     1549 * @param arg1 User defined argument.
     1550 * @param arg2 User defined argument.
     1551 * @param arg3 User defined argument.
     1552 *
     1553 * @return New session on success or NULL on error.
     1554 *
     1555 */
     1556async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch,
     1557    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
     1558{
     1559        if (exch == NULL) {
     1560                errno = ENOENT;
     1561                return NULL;
     1562        }
     1563       
     1564        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
     1565        if (sess == NULL) {
     1566                errno = ENOMEM;
     1567                return NULL;
     1568        }
     1569       
     1570        int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
     1571            0);
     1572       
     1573        if (phone < 0) {
     1574                errno = phone;
     1575                free(sess);
     1576                return NULL;
     1577        }
     1578       
     1579        sess->mgmt = mgmt;
     1580        sess->phone = phone;
     1581        sess->arg1 = arg1;
     1582        sess->arg2 = arg2;
     1583        sess->arg3 = arg3;
     1584       
     1585        list_initialize(&sess->exch_list);
     1586        fibril_mutex_initialize(&sess->mutex);
     1587        atomic_set(&sess->refcnt, 0);
     1588       
     1589        return sess;
    13801590}
    13811591
     
    13851595 * success.
    13861596 *
    1387  * @param phoneid Phone handle used for contacting the other side.
    1388  * @param arg1    User defined argument.
    1389  * @param arg2    User defined argument.
    1390  * @param arg3    User defined argument.
    1391  *
    1392  * @return New phone handle on success or a negative error code.
    1393  *
    1394  */
    1395 int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
    1396     sysarg_t arg3)
    1397 {
    1398         sysarg_t newphid;
    1399         int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
    1400             IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
    1401        
    1402         if (rc != EOK)
    1403                 return rc;
    1404        
    1405         return newphid;
     1597 * @param mgmt Exchange management style.
     1598 * @param exch Exchange for sending the message.
     1599 * @param arg1 User defined argument.
     1600 * @param arg2 User defined argument.
     1601 * @param arg3 User defined argument.
     1602 *
     1603 * @return New session on success or NULL on error.
     1604 *
     1605 */
     1606async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch,
     1607    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
     1608{
     1609        if (exch == NULL) {
     1610                errno = ENOENT;
     1611                return NULL;
     1612        }
     1613       
     1614        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
     1615        if (sess == NULL) {
     1616                errno = ENOMEM;
     1617                return NULL;
     1618        }
     1619       
     1620        int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
     1621            IPC_FLAG_BLOCKING);
     1622       
     1623        if (phone < 0) {
     1624                errno = phone;
     1625                free(sess);
     1626                return NULL;
     1627        }
     1628       
     1629        sess->mgmt = mgmt;
     1630        sess->phone = phone;
     1631        sess->arg1 = arg1;
     1632        sess->arg2 = arg2;
     1633        sess->arg3 = arg3;
     1634       
     1635        list_initialize(&sess->exch_list);
     1636        fibril_mutex_initialize(&sess->mutex);
     1637        atomic_set(&sess->refcnt, 0);
     1638       
     1639        return sess;
    14061640}
    14071641
     
    14091643 *
    14101644 */
    1411 int async_connect_kbox(task_id_t id)
    1412 {
    1413         return ipc_connect_kbox(id);
     1645async_sess_t *async_connect_kbox(task_id_t id)
     1646{
     1647        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
     1648        if (sess == NULL) {
     1649                errno = ENOMEM;
     1650                return NULL;
     1651        }
     1652       
     1653        int phone = ipc_connect_kbox(id);
     1654        if (phone < 0) {
     1655                errno = phone;
     1656                free(sess);
     1657                return NULL;
     1658        }
     1659       
     1660        sess->mgmt = EXCHANGE_ATOMIC;
     1661        sess->phone = phone;
     1662        sess->arg1 = 0;
     1663        sess->arg2 = 0;
     1664        sess->arg3 = 0;
     1665       
     1666        list_initialize(&sess->exch_list);
     1667        fibril_mutex_initialize(&sess->mutex);
     1668        atomic_set(&sess->refcnt, 0);
     1669       
     1670        return sess;
     1671}
     1672
     1673static int async_hangup_internal(int phone)
     1674{
     1675        return ipc_hangup(phone);
    14141676}
    14151677
    14161678/** Wrapper for ipc_hangup.
    14171679 *
    1418  * @param phone Phone handle to hung up.
     1680 * @param sess Session to hung up.
    14191681 *
    14201682 * @return Zero on success or a negative error code.
    14211683 *
    14221684 */
    1423 int async_hangup(int phone)
    1424 {
    1425         return ipc_hangup(phone);
     1685int async_hangup(async_sess_t *sess)
     1686{
     1687        assert(sess);
     1688       
     1689        if (atomic_get(&sess->refcnt) > 0)
     1690                return EBUSY;
     1691       
     1692        int rc = async_hangup_internal(sess->phone);
     1693        if (rc == EOK)
     1694                free(sess);
     1695       
     1696        return rc;
    14261697}
    14271698
     
    14321703}
    14331704
     1705/** Start new exchange in a session.
     1706 *
     1707 * @param session Session.
     1708 *
     1709 * @return New exchange or NULL on error.
     1710 *
     1711 */
     1712async_exch_t *async_exchange_begin(async_sess_t *sess)
     1713{
     1714        if (sess == NULL)
     1715                return NULL;
     1716       
     1717        async_exch_t *exch;
     1718       
     1719        fibril_mutex_lock(&async_sess_mutex);
     1720       
     1721        if (!list_empty(&sess->exch_list)) {
     1722                /*
     1723                 * There are inactive exchanges in the session.
     1724                 */
     1725                exch = (async_exch_t *)
     1726                    list_get_instance(sess->exch_list.next, async_exch_t, sess_link);
     1727                list_remove(&exch->sess_link);
     1728                list_remove(&exch->global_link);
     1729        } else {
     1730                /*
     1731                 * There are no available exchanges in the session.
     1732                 */
     1733               
     1734                if ((sess->mgmt == EXCHANGE_ATOMIC) ||
     1735                    (sess->mgmt == EXCHANGE_SERIALIZE)) {
     1736                        exch = (async_exch_t *) malloc(sizeof(async_exch_t));
     1737                        if (exch != NULL) {
     1738                                list_initialize(&exch->sess_link);
     1739                                list_initialize(&exch->global_link);
     1740                                exch->sess = sess;
     1741                                exch->phone = sess->phone;
     1742                        }
     1743                } else {  /* EXCHANGE_PARALLEL */
     1744                        /*
     1745                         * Make a one-time attempt to connect a new data phone.
     1746                         */
     1747                       
     1748                        int phone;
     1749                       
     1750retry:
     1751                        phone = async_connect_me_to_internal(sess->phone, sess->arg1,
     1752                            sess->arg2, sess->arg3, 0);
     1753                        if (phone >= 0) {
     1754                                exch = (async_exch_t *) malloc(sizeof(async_exch_t));
     1755                                if (exch != NULL) {
     1756                                        list_initialize(&exch->sess_link);
     1757                                        list_initialize(&exch->global_link);
     1758                                        exch->sess = sess;
     1759                                        exch->phone = phone;
     1760                                } else
     1761                                        async_hangup_internal(phone);
     1762                        } else if (!list_empty(&inactive_exch_list)) {
     1763                                /*
     1764                                 * We did not manage to connect a new phone. But we
     1765                                 * can try to close some of the currently inactive
     1766                                 * connections in other sessions and try again.
     1767                                 */
     1768                                exch = (async_exch_t *)
     1769                                    list_get_instance(inactive_exch_list.next, async_exch_t,
     1770                                    global_link);
     1771                                list_remove(&exch->sess_link);
     1772                                list_remove(&exch->global_link);
     1773                                async_hangup_internal(exch->phone);
     1774                                free(exch);
     1775                                goto retry;
     1776                        } else {
     1777                                /*
     1778                                 * Wait for a phone to become available.
     1779                                 */
     1780                                fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
     1781                                goto retry;
     1782                        }
     1783                }
     1784        }
     1785       
     1786        fibril_mutex_unlock(&async_sess_mutex);
     1787       
     1788        if (exch != NULL) {
     1789                atomic_inc(&sess->refcnt);
     1790               
     1791                if (sess->mgmt == EXCHANGE_SERIALIZE)
     1792                        fibril_mutex_lock(&sess->mutex);
     1793        }
     1794       
     1795        return exch;
     1796}
     1797
     1798/** Finish an exchange.
     1799 *
     1800 * @param exch Exchange to finish.
     1801 *
     1802 */
     1803void async_exchange_end(async_exch_t *exch)
     1804{
     1805        if (exch == NULL)
     1806                return;
     1807       
     1808        async_sess_t *sess = exch->sess;
     1809       
     1810        if (sess->mgmt == EXCHANGE_SERIALIZE)
     1811                fibril_mutex_unlock(&sess->mutex);
     1812       
     1813        fibril_mutex_lock(&async_sess_mutex);
     1814       
     1815        list_append(&exch->sess_link, &sess->exch_list);
     1816        list_append(&exch->global_link, &inactive_exch_list);
     1817        fibril_condvar_signal(&avail_phone_cv);
     1818       
     1819        fibril_mutex_unlock(&async_sess_mutex);
     1820}
     1821
    14341822/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
    14351823 *
    1436  * @param phoneid Phone that will be used to contact the receiving side.
    1437  * @param dst     Destination address space area base.
    1438  * @param size    Size of the destination address space area.
    1439  * @param arg     User defined argument.
    1440  * @param flags   Storage for the received flags. Can be NULL.
     1824 * @param exch  Exchange for sending the message.
     1825 * @param dst   Destination address space area base.
     1826 * @param size  Size of the destination address space area.
     1827 * @param arg   User defined argument.
     1828 * @param flags Storage for the received flags. Can be NULL.
    14411829 *
    14421830 * @return Zero on success or a negative error code from errno.h.
    14431831 *
    14441832 */
    1445 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
    1446     unsigned int *flags)
    1447 {
     1833int async_share_in_start(async_exch_t *exch, void *dst, size_t size,
     1834    sysarg_t arg, unsigned int *flags)
     1835{
     1836        if (exch == NULL)
     1837                return ENOENT;
     1838       
    14481839        sysarg_t tmp_flags;
    1449         int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
     1840        int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
    14501841            (sysarg_t) size, arg, NULL, &tmp_flags);
    14511842       
     
    15051896/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
    15061897 *
    1507  * @param phoneid Phone that will be used to contact the receiving side.
    1508  * @param src     Source address space area base address.
    1509  * @param flags   Flags to be used for sharing. Bits can be only cleared.
     1898 * @param exch  Exchange for sending the message.
     1899 * @param src   Source address space area base address.
     1900 * @param flags Flags to be used for sharing. Bits can be only cleared.
    15101901 *
    15111902 * @return Zero on success or a negative error code from errno.h.
    15121903 *
    15131904 */
    1514 int async_share_out_start(int phoneid, void *src, unsigned int flags)
    1515 {
    1516         return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
     1905int async_share_out_start(async_exch_t *exch, void *src, unsigned int flags)
     1906{
     1907        if (exch == NULL)
     1908                return ENOENT;
     1909       
     1910        return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
    15171911            (sysarg_t) flags);
    15181912}
     
    15671961}
    15681962
     1963/** Start IPC_M_DATA_READ using the async framework.
     1964 *
     1965 * @param exch    Exchange for sending the message.
     1966 * @param dst     Address of the beginning of the destination buffer.
     1967 * @param size    Size of the destination buffer (in bytes).
     1968 * @param dataptr Storage of call data (arg 2 holds actual data size).
     1969 *
     1970 * @return Hash of the sent message or 0 on error.
     1971 *
     1972 */
     1973aid_t async_data_read(async_exch_t *exch, void *dst, size_t size,
     1974    ipc_call_t *dataptr)
     1975{
     1976        return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst,
     1977            (sysarg_t) size, dataptr);
     1978}
     1979
    15691980/** Wrapper for IPC_M_DATA_READ calls using the async framework.
    15701981 *
    1571  * @param phoneid Phone that will be used to contact the receiving side.
    1572  * @param dst     Address of the beginning of the destination buffer.
    1573  * @param size    Size of the destination buffer.
    1574  * @param flags   Flags to control the data transfer.
     1982 * @param exch Exchange for sending the message.
     1983 * @param dst  Address of the beginning of the destination buffer.
     1984 * @param size Size of the destination buffer.
    15751985 *
    15761986 * @return Zero on success or a negative error code from errno.h.
    15771987 *
    15781988 */
    1579 int
    1580 async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
    1581 {
    1582         return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
    1583             (sysarg_t) size, (sysarg_t) flags);
     1989int async_data_read_start(async_exch_t *exch, void *dst, size_t size)
     1990{
     1991        if (exch == NULL)
     1992                return ENOENT;
     1993       
     1994        return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst,
     1995            (sysarg_t) size);
    15841996}
    15851997
     
    16362048 *
    16372049 */
    1638 int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    1639     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    1640 {
     2050int async_data_read_forward_fast(async_exch_t *exch, sysarg_t imethod,
     2051    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
     2052    ipc_call_t *dataptr)
     2053{
     2054        if (exch == NULL)
     2055                return ENOENT;
     2056       
    16412057        ipc_callid_t callid;
    16422058        if (!async_data_read_receive(&callid, NULL)) {
     
    16452061        }
    16462062       
    1647         aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
     2063        aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
    16482064            dataptr);
    16492065        if (msg == 0) {
     
    16522068        }
    16532069       
    1654         int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
     2070        int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
    16552071            IPC_FF_ROUTE_FROM_ME);
    16562072        if (retval != EOK) {
     
    16682084/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
    16692085 *
    1670  * @param phoneid Phone that will be used to contact the receiving side.
    1671  * @param src     Address of the beginning of the source buffer.
    1672  * @param size    Size of the source buffer.
    1673  * @param flags   Flags to control the data transfer.
     2086 * @param exch Exchange for sending the message.
     2087 * @param src  Address of the beginning of the source buffer.
     2088 * @param size Size of the source buffer.
    16742089 *
    16752090 * @return Zero on success or a negative error code from errno.h.
    16762091 *
    16772092 */
    1678 int
    1679 async_data_write_start_generic(int phoneid, const void *src, size_t size,
    1680     int flags)
    1681 {
    1682         return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
    1683             (sysarg_t) size, (sysarg_t) flags);
     2093int async_data_write_start(async_exch_t *exch, const void *src, size_t size)
     2094{
     2095        if (exch == NULL)
     2096                return ENOENT;
     2097       
     2098        return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src,
     2099            (sysarg_t) size);
    16842100}
    16852101
     
    17572173    size_t *received)
    17582174{
     2175        assert(data);
     2176       
    17592177        ipc_callid_t callid;
    17602178        size_t size;
     
    18242242 *
    18252243 */
    1826 int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    1827     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    1828 {
     2244int async_data_write_forward_fast(async_exch_t *exch, sysarg_t imethod,
     2245    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
     2246    ipc_call_t *dataptr)
     2247{
     2248        if (exch == NULL)
     2249                return ENOENT;
     2250       
    18292251        ipc_callid_t callid;
    18302252        if (!async_data_write_receive(&callid, NULL)) {
     
    18332255        }
    18342256       
    1835         aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
     2257        aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
    18362258            dataptr);
    18372259        if (msg == 0) {
     
    18402262        }
    18412263       
    1842         int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
     2264        int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
    18432265            IPC_FF_ROUTE_FROM_ME);
    18442266        if (retval != EOK) {
     
    18542276}
    18552277
     2278/** Wrapper for sending an exchange over different exchange for cloning
     2279 *
     2280 * @param exch       Exchange to be used for sending.
     2281 * @param clone_exch Exchange to be cloned.
     2282 *
     2283 */
     2284int async_exchange_clone(async_exch_t *exch, async_exch_t *clone_exch)
     2285{
     2286        return async_req_1_0(exch, IPC_M_CONNECTION_CLONE, clone_exch->phone);
     2287}
     2288
     2289/** Wrapper for receiving the IPC_M_CONNECTION_CLONE calls.
     2290 *
     2291 * If the current call is IPC_M_CONNECTION_CLONE then a new
     2292 * async session is created for the accepted phone.
     2293 *
     2294 * @param mgmt Exchange management style.
     2295 *
     2296 * @return New async session or NULL on failure.
     2297 *
     2298 */
     2299async_sess_t *async_clone_receive(exch_mgmt_t mgmt)
     2300{
     2301        /* Accept the phone */
     2302        ipc_call_t call;
     2303        ipc_callid_t callid = async_get_call(&call);
     2304        int phone = (int) IPC_GET_ARG1(call);
     2305       
     2306        if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
     2307            (phone < 0)) {
     2308                async_answer_0(callid, EINVAL);
     2309                return NULL;
     2310        }
     2311       
     2312        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
     2313        if (sess == NULL) {
     2314                async_answer_0(callid, ENOMEM);
     2315                return NULL;
     2316        }
     2317       
     2318        sess->mgmt = mgmt;
     2319        sess->phone = phone;
     2320        sess->arg1 = 0;
     2321        sess->arg2 = 0;
     2322        sess->arg3 = 0;
     2323       
     2324        list_initialize(&sess->exch_list);
     2325        fibril_mutex_initialize(&sess->mutex);
     2326        atomic_set(&sess->refcnt, 0);
     2327       
     2328        /* Acknowledge the cloned phone */
     2329        async_answer_0(callid, EOK);
     2330       
     2331        return sess;
     2332}
     2333
     2334/** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls.
     2335 *
     2336 * If the current call is IPC_M_CONNECT_TO_ME then a new
     2337 * async session is created for the accepted phone.
     2338 *
     2339 * @param mgmt Exchange management style.
     2340 *
     2341 * @return New async session or NULL on failure.
     2342 *
     2343 */
     2344async_sess_t *async_callback_receive(exch_mgmt_t mgmt)
     2345{
     2346        /* Accept the phone */
     2347        ipc_call_t call;
     2348        ipc_callid_t callid = async_get_call(&call);
     2349        int phone = (int) IPC_GET_ARG5(call);
     2350       
     2351        if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) ||
     2352            (phone < 0)) {
     2353                async_answer_0(callid, EINVAL);
     2354                return NULL;
     2355        }
     2356       
     2357        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
     2358        if (sess == NULL) {
     2359                async_answer_0(callid, ENOMEM);
     2360                return NULL;
     2361        }
     2362       
     2363        sess->mgmt = mgmt;
     2364        sess->phone = phone;
     2365        sess->arg1 = 0;
     2366        sess->arg2 = 0;
     2367        sess->arg3 = 0;
     2368       
     2369        list_initialize(&sess->exch_list);
     2370        fibril_mutex_initialize(&sess->mutex);
     2371        atomic_set(&sess->refcnt, 0);
     2372       
     2373        /* Acknowledge the connected phone */
     2374        async_answer_0(callid, EOK);
     2375       
     2376        return sess;
     2377}
     2378
    18562379/** @}
    18572380 */
Note: See TracChangeset for help on using the changeset viewer.