Ignore:
File:
1 edited

Legend:

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

    r79ae36dd r8e80d3f  
    4040 * programming.
    4141 *
    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.
     42 * You should be able to write very simple multithreaded programs, the async
     43 * framework will automatically take care of most synchronization problems.
    4544 *
    4645 * Example of use (pseudo C):
     
    5453 *   int fibril1(void *arg)
    5554 *   {
    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  *
     55 *     conn = async_connect_me_to();
     56 *     c1 = async_send(conn);
     57 *     c2 = async_send(conn);
    6658 *     async_wait_for(c1);
    6759 *     async_wait_for(c2);
     
    10294#include <futex.h>
    10395#include <fibril.h>
     96#include <stdio.h>
    10497#include <adt/hash_table.h>
    10598#include <adt/list.h>
     
    109102#include <arch/barrier.h>
    110103#include <bool.h>
    111 #include <malloc.h>
    112 #include <mem.h>
    113 #include <stdlib.h>
    114104#include "private/async.h"
    115105
    116 #define CLIENT_HASH_TABLE_BUCKETS  32
    117 #define CONN_HASH_TABLE_BUCKETS    32
    118 
    119 /** Async framework global futex */
    120106atomic_t async_futex = FUTEX_INITIALIZER;
    121107
     
    123109atomic_t threads_in_ipc_wait = { 0 };
    124110
    125 /** Naming service session */
    126 async_sess_t *session_ns;
    127 
    128 /** Call data */
     111typedef 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 */
    129127typedef struct {
    130128        link_t link;
    131        
    132129        ipc_callid_t callid;
    133130        ipc_call_t call;
    134131} msg_t;
    135132
    136 /* Client connection data */
    137133typedef struct {
     134        sysarg_t in_task_hash;
    138135        link_t link;
    139        
    140         sysarg_t in_task_hash;
    141         atomic_t refcnt;
     136        int refcnt;
    142137        void *data;
    143138} client_t;
    144139
    145 /* Server connection data */
    146140typedef struct {
    147141        awaiter_t wdata;
     
    152146        /** Incoming client task hash. */
    153147        sysarg_t in_task_hash;
    154        
    155148        /** Incoming phone hash. */
    156149        sysarg_t in_phone_hash;
     
    175168
    176169/** Identifier of the incoming connection handled by the current fibril. */
    177 static fibril_local connection_t *fibril_connection;
     170static fibril_local connection_t *FIBRIL_connection;
    178171
    179172static void *default_client_data_constructor(void)
     
    201194}
    202195
    203 void *async_get_client_data(void)
    204 {
    205         assert(fibril_connection);
    206         return fibril_connection->client->data;
     196void *async_client_data_get(void)
     197{
     198        assert(FIBRIL_connection);
     199        return FIBRIL_connection->client->data;
    207200}
    208201
     
    220213}
    221214
     215/**
     216 * Pointer to a fibril function that will be used to handle connections.
     217 */
     218static async_client_conn_t client_connection = default_client_connection;
     219
    222220/** Default fibril function that gets called to handle interrupt notifications.
    223221 *
     
    232230}
    233231
    234 static async_client_conn_t client_connection = default_client_connection;
     232/**
     233 * Pointer to a fibril function that will be used to handle interrupt
     234 * notifications.
     235 */
    235236static 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  */
    242 void 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  */
    252 void 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  */
    260 static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);
    261 
    262 /** List of all currently inactive exchanges.
    263  *
    264  */
    265 static LIST_INITIALIZE(inactive_exch_list);
    266 
    267 /** Condition variable to wait for a phone to become available.
    268  *
    269  */
    270 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
    271237
    272238static hash_table_t client_hash_table;
     
    274240static LIST_INITIALIZE(timeout_list);
    275241
     242#define CLIENT_HASH_TABLE_BUCKETS  32
     243#define CONN_HASH_TABLE_BUCKETS    32
     244
    276245static hash_index_t client_hash(unsigned long key[])
    277246{
    278247        assert(key);
    279        
    280248        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
    281249}
     
    283251static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
    284252{
    285         assert(key);
    286         assert(item);
    287        
    288253        client_t *client = hash_table_get_instance(item, client_t, link);
    289254        return (key[0] == client->in_task_hash);
     
    311276{
    312277        assert(key);
    313        
    314278        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
    315279}
     
    326290static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
    327291{
    328         assert(key);
    329         assert(item);
    330        
    331292        connection_t *conn = hash_table_get_instance(item, connection_t, link);
    332293        return (key[0] == conn->in_phone_hash);
     
    351312void async_insert_timeout(awaiter_t *wd)
    352313{
    353         assert(wd);
    354        
    355314        wd->to_event.occurred = false;
    356315        wd->to_event.inlist = true;
     
    385344static bool route_call(ipc_callid_t callid, ipc_call_t *call)
    386345{
    387         assert(call);
    388        
    389346        futex_down(&async_futex);
    390347       
     
    441398static int notification_fibril(void *arg)
    442399{
    443         assert(arg);
    444        
    445400        msg_t *msg = (msg_t *) arg;
    446401        interrupt_received(msg->callid, &msg->call);
     
    463418static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
    464419{
    465         assert(call);
    466        
    467420        futex_down(&async_futex);
    468421       
     
    503456ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
    504457{
    505         assert(call);
    506         assert(fibril_connection);
     458        assert(FIBRIL_connection);
    507459       
    508460        /* Why doing this?
    509          * GCC 4.1.0 coughs on fibril_connection-> dereference.
     461         * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.
    510462         * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
    511463         *           I would never expect to find so many errors in
    512464         *           a compiler.
    513465         */
    514         connection_t *conn = fibril_connection;
     466        connection_t *conn = FIBRIL_connection;
    515467       
    516468        futex_down(&async_futex);
     
    587539static int connection_fibril(void *arg)
    588540{
    589         assert(arg);
    590        
    591541        /*
    592542         * Setup fibril-local connection pointer.
    593543         */
    594         fibril_connection = (connection_t *) arg;
     544        FIBRIL_connection = (connection_t *) arg;
    595545       
    596546        futex_down(&async_futex);
     
    602552         */
    603553       
    604         unsigned long key = fibril_connection->in_task_hash;
     554        unsigned long key = FIBRIL_connection->in_task_hash;
    605555        link_t *lnk = hash_table_find(&client_hash_table, &key);
    606556       
     
    609559        if (lnk) {
    610560                client = hash_table_get_instance(lnk, client_t, link);
    611                 atomic_inc(&client->refcnt);
     561                client->refcnt++;
    612562        } else {
    613563                client = malloc(sizeof(client_t));
    614564                if (!client) {
    615                         ipc_answer_0(fibril_connection->callid, ENOMEM);
     565                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
    616566                        futex_up(&async_futex);
    617567                        return 0;
    618568                }
    619569               
    620                 client->in_task_hash = fibril_connection->in_task_hash;
     570                client->in_task_hash = FIBRIL_connection->in_task_hash;
     571               
     572                async_serialize_start();
    621573                client->data = async_client_data_create();
    622                
    623                 atomic_set(&client->refcnt, 1);
     574                async_serialize_end();
     575               
     576                client->refcnt = 1;
    624577                hash_table_insert(&client_hash_table, &key, &client->link);
    625578        }
     
    627580        futex_up(&async_futex);
    628581       
    629         fibril_connection->client = client;
     582        FIBRIL_connection->client = client;
    630583       
    631584        /*
    632585         * Call the connection handler function.
    633586         */
    634         fibril_connection->cfibril(fibril_connection->callid,
    635             &fibril_connection->call);
     587        FIBRIL_connection->cfibril(FIBRIL_connection->callid,
     588            &FIBRIL_connection->call);
    636589       
    637590        /*
     
    642595        futex_down(&async_futex);
    643596       
    644         if (atomic_predec(&client->refcnt) == 0) {
     597        if (--client->refcnt == 0) {
    645598                hash_table_remove(&client_hash_table, &key, 1);
    646599                destroy = true;
     
    661614         */
    662615        futex_down(&async_futex);
    663         key = fibril_connection->in_phone_hash;
     616        key = FIBRIL_connection->in_phone_hash;
    664617        hash_table_remove(&conn_hash_table, &key, 1);
    665618        futex_up(&async_futex);
     
    668621         * Answer all remaining messages with EHANGUP.
    669622         */
    670         while (!list_empty(&fibril_connection->msg_queue)) {
     623        while (!list_empty(&FIBRIL_connection->msg_queue)) {
    671624                msg_t *msg =
    672                     list_get_instance(fibril_connection->msg_queue.next, msg_t,
     625                    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
    673626                    link);
    674627               
     
    682635         * i.e. IPC_M_PHONE_HUNGUP.
    683636         */
    684         if (fibril_connection->close_callid)
    685                 ipc_answer_0(fibril_connection->close_callid, EOK);
    686        
    687         free(fibril_connection);
     637        if (FIBRIL_connection->close_callid)
     638                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
     639       
     640        free(FIBRIL_connection);
    688641        return 0;
    689642}
     
    691644/** Create a new fibril for a new connection.
    692645 *
    693  * Create new fibril for connection, fill in connection structures and insert
     646 * Create new fibril for connection, fill in connection structures and inserts
    694647 * it into the hash table, so that later we can easily do routing of messages to
    695648 * particular fibrils.
     
    710663fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
    711664    ipc_callid_t callid, ipc_call_t *call,
    712     async_client_conn_t cfibril)
     665    void (*cfibril)(ipc_callid_t, ipc_call_t *))
    713666{
    714667        connection_t *conn = malloc(sizeof(*conn));
     
    766719static void handle_call(ipc_callid_t callid, ipc_call_t *call)
    767720{
    768         assert(call);
    769        
    770721        /* Unrouted call - take some default action */
    771722        if ((callid & IPC_CALLID_NOTIFICATION)) {
     
    925876void __async_init(void)
    926877{
    927         if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
    928             1, &client_hash_table_ops))
     878        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
     879            &client_hash_table_ops))
    929880                abort();
    930881       
    931         if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
    932             1, &conn_hash_table_ops))
     882        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
     883            &conn_hash_table_ops))
    933884                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);
    948885}
    949886
     
    960897 *
    961898 */
    962 void reply_received(void *arg, int retval, ipc_call_t *data)
    963 {
    964         assert(arg);
    965        
     899static void reply_received(void *arg, int retval, ipc_call_t *data)
     900{
    966901        futex_down(&async_futex);
    967902       
     
    993928 * completion.
    994929 *
    995  * @param exch    Exchange for sending the message.
    996  * @param imethod Service-defined interface and method.
     930 * @param phoneid Handle of the phone that will be used for the send.
     931 * @param method  Service-defined method.
    997932 * @param arg1    Service-defined payload argument.
    998933 * @param arg2    Service-defined payload argument.
     
    1005940 *
    1006941 */
    1007 aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     942aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    1008943    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    1009944{
    1010         if (exch == NULL)
    1011                 return 0;
    1012        
    1013945        amsg_t *msg = malloc(sizeof(amsg_t));
    1014         if (msg == NULL)
     946       
     947        if (!msg)
    1015948                return 0;
    1016949       
     
    1026959        msg->wdata.active = true;
    1027960       
    1028         ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,
     961        ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
    1029962            reply_received, true);
    1030963       
     
    1037970 * completion.
    1038971 *
    1039  * @param exch    Exchange for sending the message.
    1040  * @param imethod Service-defined interface and method.
     972 * @param phoneid Handle of the phone that will be used for the send.
     973 * @param method  Service-defined method.
    1041974 * @param arg1    Service-defined payload argument.
    1042975 * @param arg2    Service-defined payload argument.
     
    1050983 *
    1051984 */
    1052 aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     985aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
    1053986    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    1054987    ipc_call_t *dataptr)
    1055988{
    1056         if (exch == NULL)
    1057                 return 0;
    1058        
    1059989        amsg_t *msg = malloc(sizeof(amsg_t));
    1060990       
    1061         if (msg == NULL)
     991        if (!msg)
    1062992                return 0;
    1063993       
     
    10731003        msg->wdata.active = true;
    10741004       
    1075         ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,
    1076             msg, reply_received, true);
     1005        ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
     1006            reply_received, true);
    10771007       
    10781008        return (aid_t) msg;
     
    10881018void async_wait_for(aid_t amsgid, sysarg_t *retval)
    10891019{
    1090         assert(amsgid);
    1091        
    10921020        amsg_t *msg = (amsg_t *) amsgid;
    10931021       
     
    11261054int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout)
    11271055{
    1128         assert(amsgid);
    1129        
    11301056        amsg_t *msg = (amsg_t *) amsgid;
    11311057       
     
    11961122}
    11971123
     1124/** Setter for client_connection function pointer.
     1125 *
     1126 * @param conn Function that will implement a new connection fibril.
     1127 *
     1128 */
     1129void 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 */
     1139void async_set_interrupt_received(async_client_conn_t intr)
     1140{
     1141        interrupt_received = intr;
     1142}
     1143
    11981144/** Pseudo-synchronous message sending - fast version.
    11991145 *
     
    12031149 * transferring more arguments, see the slower async_req_slow().
    12041150 *
    1205  * @param exch    Exchange for sending the message.
    1206  * @param imethod Interface and method of the call.
     1151 * @param phoneid Hash of the phone through which to make the call.
     1152 * @param method  Method of the call.
    12071153 * @param arg1    Service-defined payload argument.
    12081154 * @param arg2    Service-defined payload argument.
     
    12181164 *
    12191165 */
    1220 sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1166sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    12211167    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
    12221168    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
    12231169{
    1224         if (exch == NULL)
    1225                 return ENOENT;
    1226        
    12271170        ipc_call_t result;
    1228         aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,
     1171        aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
    12291172            &result);
    12301173       
    12311174        sysarg_t rc;
    1232         async_wait_for(aid, &rc);
     1175        async_wait_for(eid, &rc);
    12331176       
    12341177        if (r1)
     
    12541197 * Send message asynchronously and return only after the reply arrives.
    12551198 *
    1256  * @param exch    Exchange for sending the message.
    1257  * @param imethod Interface and method of the call.
     1199 * @param phoneid Hash of the phone through which to make the call.
     1200 * @param method  Method of the call.
    12581201 * @param arg1    Service-defined payload argument.
    12591202 * @param arg2    Service-defined payload argument.
     
    12701213 *
    12711214 */
    1272 sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1215sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
    12731216    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
    12741217    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
    12751218{
    1276         if (exch == NULL)
    1277                 return ENOENT;
    1278        
    12791219        ipc_call_t result;
    1280         aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,
     1220        aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
    12811221            &result);
    12821222       
    12831223        sysarg_t rc;
    1284         async_wait_for(aid, &rc);
     1224        async_wait_for(eid, &rc);
    12851225       
    12861226        if (r1)
     
    13021242}
    13031243
    1304 void 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 
    1310 void 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 
    1316 void 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 
    1324 void 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 
    1332 void 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 
    1340 void 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);
     1244void async_msg_0(int phone, sysarg_t imethod)
     1245{
     1246        ipc_call_async_0(phone, imethod, NULL, NULL, true);
     1247}
     1248
     1249void 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
     1254void 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
     1259void 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
     1265void 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
     1272void 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);
    13461277}
    13471278
     
    13801311}
    13811312
    1382 int 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 
    1391 int 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);
     1313int 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
     1319int 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);
    14001325}
    14011326
     
    14041329 * Ask through phone for a new connection to some service.
    14051330 *
    1406  * @param exch            Exchange for sending the message.
     1331 * @param phone           Phone handle used for contacting the other side.
    14071332 * @param arg1            User defined argument.
    14081333 * @param arg2            User defined argument.
     
    14101335 * @param client_receiver Connection handing routine.
    14111336 *
    1412  * @return Zero on success or a negative error code.
    1413  *
    1414  */
    1415 int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
     1337 * @return New phone handle on success or a negative error code.
     1338 *
     1339 */
     1340int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
    14161341    sysarg_t arg3, async_client_conn_t client_receiver)
    14171342{
    1418         if (exch == NULL)
    1419                 return ENOENT;
    1420        
    14211343        sysarg_t task_hash;
    14221344        sysarg_t phone_hash;
    1423         int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
     1345        int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    14241346            NULL, NULL, NULL, &task_hash, &phone_hash);
    14251347        if (rc != EOK)
     
    14331355}
    14341356
    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  */
    1445 async_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 
    1511 static 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);
     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 */
     1369int 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);
    15361375       
    15371376        if (rc != EOK)
    15381377                return rc;
    15391378       
    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  */
    1556 async_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;
     1379        return newphid;
    15901380}
    15911381
     
    15951385 * success.
    15961386 *
    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  */
    1606 async_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;
     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 */
     1395int 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;
    16401406}
    16411407
     
    16431409 *
    16441410 */
    1645 async_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 
    1673 static int async_hangup_internal(int phone)
     1411int async_connect_kbox(task_id_t id)
     1412{
     1413        return ipc_connect_kbox(id);
     1414}
     1415
     1416/** Wrapper for ipc_hangup.
     1417 *
     1418 * @param phone Phone handle to hung up.
     1419 *
     1420 * @return Zero on success or a negative error code.
     1421 *
     1422 */
     1423int async_hangup(int phone)
    16741424{
    16751425        return ipc_hangup(phone);
    1676 }
    1677 
    1678 /** Wrapper for ipc_hangup.
    1679  *
    1680  * @param sess Session to hung up.
    1681  *
    1682  * @return Zero on success or a negative error code.
    1683  *
    1684  */
    1685 int 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;
    16971426}
    16981427
     
    17031432}
    17041433
    1705 /** Start new exchange in a session.
    1706  *
    1707  * @param session Session.
    1708  *
    1709  * @return New exchange or NULL on error.
    1710  *
    1711  */
    1712 async_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                        
    1750 retry:
    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  */
    1803 void 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 
    18221434/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
    18231435 *
    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.
     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.
    18291441 *
    18301442 * @return Zero on success or a negative error code from errno.h.
    18311443 *
    18321444 */
    1833 int 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        
     1445int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
     1446    unsigned int *flags)
     1447{
    18391448        sysarg_t tmp_flags;
    1840         int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
     1449        int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
    18411450            (sysarg_t) size, arg, NULL, &tmp_flags);
    18421451       
     
    18961505/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
    18971506 *
    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.
     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.
    19011510 *
    19021511 * @return Zero on success or a negative error code from errno.h.
    19031512 *
    19041513 */
    1905 int 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,
     1514int 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,
    19111517            (sysarg_t) flags);
    19121518}
     
    19611567}
    19621568
    1963 /** Start IPC_M_DATA_READ using the async framework.
    1964  *
    1965  * @param exch    Exchange for sending the message.
     1569/** Wrapper for IPC_M_DATA_READ calls using the async framework.
     1570 *
     1571 * @param phoneid Phone that will be used to contact the receiving side.
    19661572 * @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  */
    1973 aid_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 
    1980 /** Wrapper for IPC_M_DATA_READ calls using the async framework.
    1981  *
    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.
     1573 * @param size    Size of the destination buffer.
     1574 * @param flags   Flags to control the data transfer.
    19851575 *
    19861576 * @return Zero on success or a negative error code from errno.h.
    19871577 *
    19881578 */
    1989 int 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);
     1579int
     1580async_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);
    19961584}
    19971585
     
    20481636 *
    20491637 */
    2050 int 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        
     1638int 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{
    20571641        ipc_callid_t callid;
    20581642        if (!async_data_read_receive(&callid, NULL)) {
     
    20611645        }
    20621646       
    2063         aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
     1647        aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
    20641648            dataptr);
    20651649        if (msg == 0) {
     
    20681652        }
    20691653       
    2070         int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
     1654        int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
    20711655            IPC_FF_ROUTE_FROM_ME);
    20721656        if (retval != EOK) {
     
    20841668/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
    20851669 *
    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.
     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.
    20891674 *
    20901675 * @return Zero on success or a negative error code from errno.h.
    20911676 *
    20921677 */
    2093 int 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);
     1678int
     1679async_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);
    21001684}
    21011685
     
    21731757    size_t *received)
    21741758{
    2175         assert(data);
    2176        
    21771759        ipc_callid_t callid;
    21781760        size_t size;
     
    22421824 *
    22431825 */
    2244 int 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        
     1826int 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{
    22511829        ipc_callid_t callid;
    22521830        if (!async_data_write_receive(&callid, NULL)) {
     
    22551833        }
    22561834       
    2257         aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
     1835        aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
    22581836            dataptr);
    22591837        if (msg == 0) {
     
    22621840        }
    22631841       
    2264         int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
     1842        int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
    22651843            IPC_FF_ROUTE_FROM_ME);
    22661844        if (retval != EOK) {
     
    22761854}
    22771855
    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  */
    2284 int 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  */
    2299 async_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  */
    2344 async_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 
    23791856/** @}
    23801857 */
Note: See TracChangeset for help on using the changeset viewer.