Ignore:
File:
1 edited

Legend:

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

    r3815efb rc7bbf029  
    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>
     104#include <stdlib.h>
    111105#include <malloc.h>
    112 #include <mem.h>
    113 #include <stdlib.h>
    114106#include "private/async.h"
    115107
    116 #define CLIENT_HASH_TABLE_BUCKETS  32
    117 #define CONN_HASH_TABLE_BUCKETS    32
    118 
    119 /** Async framework global futex */
    120108atomic_t async_futex = FUTEX_INITIALIZER;
    121109
     
    123111atomic_t threads_in_ipc_wait = { 0 };
    124112
    125 /** Naming service session */
    126 async_sess_t *session_ns;
    127 
    128 /** Call data */
     113typedef struct {
     114        awaiter_t wdata;
     115       
     116        /** If reply was received. */
     117        bool done;
     118       
     119        /** Pointer to where the answer data is stored. */
     120        ipc_call_t *dataptr;
     121       
     122        sysarg_t retval;
     123} amsg_t;
     124
     125/**
     126 * Structures of this type are used to group information about
     127 * a call and about a message queue link.
     128 */
    129129typedef struct {
    130130        link_t link;
    131        
    132131        ipc_callid_t callid;
    133132        ipc_call_t call;
    134133} msg_t;
    135134
    136 /* Client connection data */
    137135typedef struct {
     136        sysarg_t in_task_hash;
    138137        link_t link;
    139        
    140         sysarg_t in_task_hash;
    141         atomic_t refcnt;
     138        int refcnt;
    142139        void *data;
    143140} client_t;
    144141
    145 /* Server connection data */
    146142typedef struct {
    147143        awaiter_t wdata;
     
    152148        /** Incoming client task hash. */
    153149        sysarg_t in_task_hash;
    154        
    155150        /** Incoming phone hash. */
    156151        sysarg_t in_phone_hash;
     
    160155       
    161156        /** Messages that should be delivered to this fibril. */
    162         list_t msg_queue;
     157        link_t msg_queue;
    163158       
    164159        /** Identification of the opening call. */
     
    166161        /** Call data of the opening call. */
    167162        ipc_call_t call;
    168         /** Local argument or NULL if none. */
    169         void *carg;
    170163       
    171164        /** Identification of the closing call. */
     
    173166       
    174167        /** Fibril function that will be used to handle the connection. */
    175         async_client_conn_t cfibril;
     168        void (*cfibril)(ipc_callid_t, ipc_call_t *);
    176169} connection_t;
    177170
    178171/** Identifier of the incoming connection handled by the current fibril. */
    179 static fibril_local connection_t *fibril_connection;
     172static fibril_local connection_t *FIBRIL_connection;
    180173
    181174static void *default_client_data_constructor(void)
     
    203196}
    204197
    205 void *async_get_client_data(void)
    206 {
    207         assert(fibril_connection);
    208         return fibril_connection->client->data;
     198void *async_client_data_get(void)
     199{
     200        assert(FIBRIL_connection);
     201        return FIBRIL_connection->client->data;
    209202}
    210203
     
    215208 * @param callid Hash of the incoming call.
    216209 * @param call   Data of the incoming call.
    217  * @param arg    Local argument
    218  *
    219  */
    220 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call,
    221     void *arg)
     210 *
     211 */
     212static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
    222213{
    223214        ipc_answer_0(callid, ENOENT);
    224215}
     216
     217/**
     218 * Pointer to a fibril function that will be used to handle connections.
     219 */
     220static async_client_conn_t client_connection = default_client_connection;
    225221
    226222/** Default fibril function that gets called to handle interrupt notifications.
     
    230226 * @param callid Hash of the incoming call.
    231227 * @param call   Data of the incoming call.
    232  * @param arg    Local argument.
    233228 *
    234229 */
     
    237232}
    238233
    239 static async_client_conn_t client_connection = default_client_connection;
    240 static async_interrupt_handler_t interrupt_received = default_interrupt_received;
    241 
    242 /** Setter for client_connection function pointer.
    243  *
    244  * @param conn Function that will implement a new connection fibril.
    245  *
    246  */
    247 void async_set_client_connection(async_client_conn_t conn)
    248 {
    249         client_connection = conn;
    250 }
    251 
    252 /** Setter for interrupt_received function pointer.
    253  *
    254  * @param intr Function that will implement a new interrupt
    255  *             notification fibril.
    256  */
    257 void async_set_interrupt_received(async_interrupt_handler_t intr)
    258 {
    259         interrupt_received = intr;
    260 }
    261 
    262 /** Mutex protecting inactive_exch_list and avail_phone_cv.
    263  *
    264  */
    265 static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);
    266 
    267 /** List of all currently inactive exchanges.
    268  *
    269  */
    270 static LIST_INITIALIZE(inactive_exch_list);
    271 
    272 /** Condition variable to wait for a phone to become available.
    273  *
    274  */
    275 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
     234/**
     235 * Pointer to a fibril function that will be used to handle interrupt
     236 * notifications.
     237 */
     238static async_client_conn_t interrupt_received = default_interrupt_received;
    276239
    277240static hash_table_t client_hash_table;
     
    279242static LIST_INITIALIZE(timeout_list);
    280243
     244#define CLIENT_HASH_TABLE_BUCKETS  32
     245#define CONN_HASH_TABLE_BUCKETS    32
     246
    281247static hash_index_t client_hash(unsigned long key[])
    282248{
    283249        assert(key);
    284        
    285250        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
    286251}
     
    288253static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
    289254{
    290         assert(key);
    291         assert(item);
    292        
    293255        client_t *client = hash_table_get_instance(item, client_t, link);
    294256        return (key[0] == client->in_task_hash);
     
    316278{
    317279        assert(key);
    318        
    319280        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
    320281}
     
    331292static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
    332293{
    333         assert(key);
    334         assert(item);
    335        
    336294        connection_t *conn = hash_table_get_instance(item, connection_t, link);
    337295        return (key[0] == conn->in_phone_hash);
     
    356314void async_insert_timeout(awaiter_t *wd)
    357315{
    358         assert(wd);
    359        
    360316        wd->to_event.occurred = false;
    361317        wd->to_event.inlist = true;
    362318       
    363         link_t *tmp = timeout_list.head.next;
    364         while (tmp != &timeout_list.head) {
     319        link_t *tmp = timeout_list.next;
     320        while (tmp != &timeout_list) {
    365321                awaiter_t *cur
    366322                    = list_get_instance(tmp, awaiter_t, to_event.link);
     
    372328        }
    373329       
    374         list_insert_before(&wd->to_event.link, tmp);
     330        list_append(&wd->to_event.link, tmp);
    375331}
    376332
     
    390346static bool route_call(ipc_callid_t callid, ipc_call_t *call)
    391347{
    392         assert(call);
    393        
    394348        futex_down(&async_futex);
    395349       
     
    446400static int notification_fibril(void *arg)
    447401{
    448         assert(arg);
    449        
    450402        msg_t *msg = (msg_t *) arg;
    451403        interrupt_received(msg->callid, &msg->call);
     
    468420static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
    469421{
    470         assert(call);
    471        
    472422        futex_down(&async_futex);
    473423       
     
    508458ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
    509459{
    510         assert(call);
    511         assert(fibril_connection);
     460        assert(FIBRIL_connection);
    512461       
    513462        /* Why doing this?
    514          * GCC 4.1.0 coughs on fibril_connection-> dereference.
     463         * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.
    515464         * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
    516465         *           I would never expect to find so many errors in
    517466         *           a compiler.
    518467         */
    519         connection_t *conn = fibril_connection;
     468        connection_t *conn = FIBRIL_connection;
    520469       
    521470        futex_down(&async_futex);
     
    569518        }
    570519       
    571         msg_t *msg = list_get_instance(list_first(&conn->msg_queue), msg_t, link);
     520        msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link);
    572521        list_remove(&msg->link);
    573522       
     
    592541static int connection_fibril(void *arg)
    593542{
    594         assert(arg);
    595        
    596543        /*
    597544         * Setup fibril-local connection pointer.
    598545         */
    599         fibril_connection = (connection_t *) arg;
     546        FIBRIL_connection = (connection_t *) arg;
    600547       
    601548        futex_down(&async_futex);
     
    607554         */
    608555       
    609         unsigned long key = fibril_connection->in_task_hash;
     556        unsigned long key = FIBRIL_connection->in_task_hash;
    610557        link_t *lnk = hash_table_find(&client_hash_table, &key);
    611558       
     
    614561        if (lnk) {
    615562                client = hash_table_get_instance(lnk, client_t, link);
    616                 atomic_inc(&client->refcnt);
     563                client->refcnt++;
    617564        } else {
    618565                client = malloc(sizeof(client_t));
    619566                if (!client) {
    620                         ipc_answer_0(fibril_connection->callid, ENOMEM);
     567                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
    621568                        futex_up(&async_futex);
    622569                        return 0;
    623570                }
    624571               
    625                 client->in_task_hash = fibril_connection->in_task_hash;
     572                client->in_task_hash = FIBRIL_connection->in_task_hash;
     573               
     574                async_serialize_start();
    626575                client->data = async_client_data_create();
    627                
    628                 atomic_set(&client->refcnt, 1);
     576                async_serialize_end();
     577               
     578                client->refcnt = 1;
    629579                hash_table_insert(&client_hash_table, &key, &client->link);
    630580        }
     
    632582        futex_up(&async_futex);
    633583       
    634         fibril_connection->client = client;
     584        FIBRIL_connection->client = client;
    635585       
    636586        /*
    637587         * Call the connection handler function.
    638588         */
    639         fibril_connection->cfibril(fibril_connection->callid,
    640             &fibril_connection->call, fibril_connection->carg);
     589        FIBRIL_connection->cfibril(FIBRIL_connection->callid,
     590            &FIBRIL_connection->call);
    641591       
    642592        /*
     
    647597        futex_down(&async_futex);
    648598       
    649         if (atomic_predec(&client->refcnt) == 0) {
     599        if (--client->refcnt == 0) {
    650600                hash_table_remove(&client_hash_table, &key, 1);
    651601                destroy = true;
     
    666616         */
    667617        futex_down(&async_futex);
    668         key = fibril_connection->in_phone_hash;
     618        key = FIBRIL_connection->in_phone_hash;
    669619        hash_table_remove(&conn_hash_table, &key, 1);
    670620        futex_up(&async_futex);
     
    673623         * Answer all remaining messages with EHANGUP.
    674624         */
    675         while (!list_empty(&fibril_connection->msg_queue)) {
     625        while (!list_empty(&FIBRIL_connection->msg_queue)) {
    676626                msg_t *msg =
    677                     list_get_instance(list_first(&fibril_connection->msg_queue),
    678                     msg_t, link);
     627                    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
     628                    link);
    679629               
    680630                list_remove(&msg->link);
     
    687637         * i.e. IPC_M_PHONE_HUNGUP.
    688638         */
    689         if (fibril_connection->close_callid)
    690                 ipc_answer_0(fibril_connection->close_callid, EOK);
    691        
    692         free(fibril_connection);
     639        if (FIBRIL_connection->close_callid)
     640                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
     641       
     642        free(FIBRIL_connection);
    693643        return 0;
    694644}
     
    696646/** Create a new fibril for a new connection.
    697647 *
    698  * Create new fibril for connection, fill in connection structures and insert
     648 * Create new fibril for connection, fill in connection structures and inserts
    699649 * it into the hash table, so that later we can easily do routing of messages to
    700650 * particular fibrils.
     
    709659 * @param cfibril       Fibril function that should be called upon opening the
    710660 *                      connection.
    711  * @param carg          Extra argument to pass to the connection fibril
    712661 *
    713662 * @return New fibril id or NULL on failure.
     
    716665fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
    717666    ipc_callid_t callid, ipc_call_t *call,
    718     async_client_conn_t cfibril, void *carg)
     667    void (*cfibril)(ipc_callid_t, ipc_call_t *))
    719668{
    720669        connection_t *conn = malloc(sizeof(*conn));
     
    731680        conn->callid = callid;
    732681        conn->close_callid = 0;
    733         conn->carg = carg;
    734682       
    735683        if (call)
     
    773721static void handle_call(ipc_callid_t callid, ipc_call_t *call)
    774722{
    775         assert(call);
    776        
    777723        /* Unrouted call - take some default action */
    778724        if ((callid & IPC_CALLID_NOTIFICATION)) {
     
    786732                /* Open new connection with fibril, etc. */
    787733                async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
    788                     callid, call, client_connection, NULL);
     734                    callid, call, client_connection);
    789735                return;
    790736        }
     
    806752        futex_down(&async_futex);
    807753       
    808         link_t *cur = list_first(&timeout_list);
    809         while (cur != NULL) {
     754        link_t *cur = timeout_list.next;
     755        while (cur != &timeout_list) {
    810756                awaiter_t *waiter =
    811757                    list_get_instance(cur, awaiter_t, to_event.link);
     
    813759                if (tv_gt(&waiter->to_event.expires, &tv))
    814760                        break;
     761               
     762                cur = cur->next;
    815763               
    816764                list_remove(&waiter->to_event.link);
     
    826774                        fibril_add_ready(waiter->fid);
    827775                }
    828                
    829                 cur = list_first(&timeout_list);
    830776        }
    831777       
     
    854800                suseconds_t timeout;
    855801                if (!list_empty(&timeout_list)) {
    856                         awaiter_t *waiter = list_get_instance(
    857                             list_first(&timeout_list), awaiter_t, to_event.link);
     802                        awaiter_t *waiter = list_get_instance(timeout_list.next,
     803                            awaiter_t, to_event.link);
    858804                       
    859805                        struct timeval tv;
     
    932878void __async_init(void)
    933879{
    934         if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
    935             1, &client_hash_table_ops))
     880        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
     881            &client_hash_table_ops))
    936882                abort();
    937883       
    938         if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
    939             1, &conn_hash_table_ops))
     884        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
     885            &conn_hash_table_ops))
    940886                abort();
    941        
    942         session_ns = (async_sess_t *) malloc(sizeof(async_sess_t));
    943         if (session_ns == NULL)
    944                 abort();
    945        
    946         session_ns->mgmt = EXCHANGE_ATOMIC;
    947         session_ns->phone = PHONE_NS;
    948         session_ns->arg1 = 0;
    949         session_ns->arg2 = 0;
    950         session_ns->arg3 = 0;
    951        
    952         list_initialize(&session_ns->exch_list);
    953         fibril_mutex_initialize(&session_ns->mutex);
    954         atomic_set(&session_ns->refcnt, 0);
    955887}
    956888
     
    967899 *
    968900 */
    969 void reply_received(void *arg, int retval, ipc_call_t *data)
    970 {
    971         assert(arg);
    972        
     901static void reply_received(void *arg, int retval, ipc_call_t *data)
     902{
    973903        futex_down(&async_futex);
    974904       
     
    1000930 * completion.
    1001931 *
    1002  * @param exch    Exchange for sending the message.
    1003  * @param imethod Service-defined interface and method.
     932 * @param phoneid Handle of the phone that will be used for the send.
     933 * @param method  Service-defined method.
    1004934 * @param arg1    Service-defined payload argument.
    1005935 * @param arg2    Service-defined payload argument.
     
    1012942 *
    1013943 */
    1014 aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     944aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    1015945    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    1016946{
    1017         if (exch == NULL)
    1018                 return 0;
    1019        
    1020947        amsg_t *msg = malloc(sizeof(amsg_t));
    1021         if (msg == NULL)
     948       
     949        if (!msg)
    1022950                return 0;
    1023951       
     
    1033961        msg->wdata.active = true;
    1034962       
    1035         ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,
     963        ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
    1036964            reply_received, true);
    1037965       
     
    1044972 * completion.
    1045973 *
    1046  * @param exch    Exchange for sending the message.
    1047  * @param imethod Service-defined interface and method.
     974 * @param phoneid Handle of the phone that will be used for the send.
     975 * @param method  Service-defined method.
    1048976 * @param arg1    Service-defined payload argument.
    1049977 * @param arg2    Service-defined payload argument.
     
    1057985 *
    1058986 */
    1059 aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     987aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
    1060988    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    1061989    ipc_call_t *dataptr)
    1062990{
    1063         if (exch == NULL)
    1064                 return 0;
    1065        
    1066991        amsg_t *msg = malloc(sizeof(amsg_t));
    1067992       
    1068         if (msg == NULL)
     993        if (!msg)
    1069994                return 0;
    1070995       
     
    10801005        msg->wdata.active = true;
    10811006       
    1082         ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,
    1083             msg, reply_received, true);
     1007        ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
     1008            reply_received, true);
    10841009       
    10851010        return (aid_t) msg;
     
    10951020void async_wait_for(aid_t amsgid, sysarg_t *retval)
    10961021{
    1097         assert(amsgid);
    1098        
    10991022        amsg_t *msg = (amsg_t *) amsgid;
    11001023       
     
    11331056int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout)
    11341057{
    1135         assert(amsgid);
    1136        
    11371058        amsg_t *msg = (amsg_t *) amsgid;
    11381059       
     
    12031124}
    12041125
     1126/** Setter for client_connection function pointer.
     1127 *
     1128 * @param conn Function that will implement a new connection fibril.
     1129 *
     1130 */
     1131void async_set_client_connection(async_client_conn_t conn)
     1132{
     1133        client_connection = conn;
     1134}
     1135
     1136/** Setter for interrupt_received function pointer.
     1137 *
     1138 * @param intr Function that will implement a new interrupt
     1139 *             notification fibril.
     1140 */
     1141void async_set_interrupt_received(async_client_conn_t intr)
     1142{
     1143        interrupt_received = intr;
     1144}
     1145
    12051146/** Pseudo-synchronous message sending - fast version.
    12061147 *
     
    12101151 * transferring more arguments, see the slower async_req_slow().
    12111152 *
    1212  * @param exch    Exchange for sending the message.
    1213  * @param imethod Interface and method of the call.
     1153 * @param phoneid Hash of the phone through which to make the call.
     1154 * @param method  Method of the call.
    12141155 * @param arg1    Service-defined payload argument.
    12151156 * @param arg2    Service-defined payload argument.
     
    12251166 *
    12261167 */
    1227 sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1168sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    12281169    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
    12291170    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
    12301171{
    1231         if (exch == NULL)
    1232                 return ENOENT;
    1233        
    12341172        ipc_call_t result;
    1235         aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,
     1173        aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
    12361174            &result);
    12371175       
    12381176        sysarg_t rc;
    1239         async_wait_for(aid, &rc);
     1177        async_wait_for(eid, &rc);
    12401178       
    12411179        if (r1)
     
    12611199 * Send message asynchronously and return only after the reply arrives.
    12621200 *
    1263  * @param exch    Exchange for sending the message.
    1264  * @param imethod Interface and method of the call.
     1201 * @param phoneid Hash of the phone through which to make the call.
     1202 * @param method  Method of the call.
    12651203 * @param arg1    Service-defined payload argument.
    12661204 * @param arg2    Service-defined payload argument.
     
    12771215 *
    12781216 */
    1279 sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1217sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
    12801218    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
    12811219    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
    12821220{
    1283         if (exch == NULL)
    1284                 return ENOENT;
    1285        
    12861221        ipc_call_t result;
    1287         aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,
     1222        aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
    12881223            &result);
    12891224       
    12901225        sysarg_t rc;
    1291         async_wait_for(aid, &rc);
     1226        async_wait_for(eid, &rc);
    12921227       
    12931228        if (r1)
     
    13091244}
    13101245
    1311 void async_msg_0(async_exch_t *exch, sysarg_t imethod)
    1312 {
    1313         if (exch != NULL)
    1314                 ipc_call_async_0(exch->phone, imethod, NULL, NULL, true);
    1315 }
    1316 
    1317 void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)
    1318 {
    1319         if (exch != NULL)
    1320                 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true);
    1321 }
    1322 
    1323 void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    1324     sysarg_t arg2)
    1325 {
    1326         if (exch != NULL)
    1327                 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL,
    1328                     true);
    1329 }
    1330 
    1331 void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    1332     sysarg_t arg2, sysarg_t arg3)
    1333 {
    1334         if (exch != NULL)
    1335                 ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL,
    1336                     NULL, true);
    1337 }
    1338 
    1339 void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    1340     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
    1341 {
    1342         if (exch != NULL)
    1343                 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,
    1344                     NULL, NULL, true);
    1345 }
    1346 
    1347 void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    1348     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
    1349 {
    1350         if (exch != NULL)
    1351                 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,
    1352                     arg5, NULL, NULL, true);
     1246void async_msg_0(int phone, sysarg_t imethod)
     1247{
     1248        ipc_call_async_0(phone, imethod, NULL, NULL, true);
     1249}
     1250
     1251void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
     1252{
     1253        ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
     1254}
     1255
     1256void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
     1257{
     1258        ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
     1259}
     1260
     1261void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     1262    sysarg_t arg3)
     1263{
     1264        ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
     1265}
     1266
     1267void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     1268    sysarg_t arg3, sysarg_t arg4)
     1269{
     1270        ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
     1271            true);
     1272}
     1273
     1274void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     1275    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
     1276{
     1277        ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
     1278            NULL, true);
    13531279}
    13541280
     
    13871313}
    13881314
    1389 int async_forward_fast(ipc_callid_t callid, async_exch_t *exch,
    1390     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
    1391 {
    1392         if (exch == NULL)
    1393                 return ENOENT;
    1394        
    1395         return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode);
    1396 }
    1397 
    1398 int async_forward_slow(ipc_callid_t callid, async_exch_t *exch,
    1399     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    1400     sysarg_t arg4, sysarg_t arg5, unsigned int mode)
    1401 {
    1402         if (exch == NULL)
    1403                 return ENOENT;
    1404        
    1405         return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3,
    1406             arg4, arg5, mode);
     1315int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     1316    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
     1317{
     1318        return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
     1319}
     1320
     1321int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     1322    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
     1323    unsigned int mode)
     1324{
     1325        return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
     1326            arg5, mode);
    14071327}
    14081328
     
    14111331 * Ask through phone for a new connection to some service.
    14121332 *
    1413  * @param exch            Exchange for sending the message.
     1333 * @param phone           Phone handle used for contacting the other side.
    14141334 * @param arg1            User defined argument.
    14151335 * @param arg2            User defined argument.
     
    14171337 * @param client_receiver Connection handing routine.
    14181338 *
    1419  * @return Zero on success or a negative error code.
    1420  *
    1421  */
    1422 int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
    1423     sysarg_t arg3, async_client_conn_t client_receiver, void *carg)
    1424 {
    1425         if (exch == NULL)
    1426                 return ENOENT;
    1427        
     1339 * @return New phone handle on success or a negative error code.
     1340 *
     1341 */
     1342int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
     1343    sysarg_t arg3, async_client_conn_t client_receiver)
     1344{
    14281345        sysarg_t task_hash;
    14291346        sysarg_t phone_hash;
    1430         int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
     1347        int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    14311348            NULL, NULL, NULL, &task_hash, &phone_hash);
    14321349        if (rc != EOK)
     
    14351352        if (client_receiver != NULL)
    14361353                async_new_connection(task_hash, phone_hash, 0, NULL,
    1437                     client_receiver, carg);
     1354                    client_receiver);
    14381355       
    14391356        return EOK;
    14401357}
    14411358
    1442 /** Wrapper for making IPC_M_CONNECT_ME calls using the async framework.
    1443  *
    1444  * Ask through for a cloned connection to some service.
    1445  *
    1446  * @param mgmt Exchange management style.
    1447  * @param exch Exchange for sending the message.
    1448  *
    1449  * @return New session on success or NULL on error.
    1450  *
    1451  */
    1452 async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch)
    1453 {
    1454         if (exch == NULL) {
    1455                 errno = ENOENT;
    1456                 return NULL;
    1457         }
    1458        
    1459         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    1460         if (sess == NULL) {
    1461                 errno = ENOMEM;
    1462                 return NULL;
    1463         }
    1464        
    1465         ipc_call_t result;
    1466        
    1467         amsg_t *msg = malloc(sizeof(amsg_t));
    1468         if (msg == NULL) {
    1469                 free(sess);
    1470                 errno = ENOMEM;
    1471                 return NULL;
    1472         }
    1473        
    1474         msg->done = false;
    1475         msg->dataptr = &result;
    1476        
    1477         msg->wdata.to_event.inlist = false;
    1478        
    1479         /*
    1480          * We may sleep in the next method,
    1481          * but it will use its own means
    1482          */
    1483         msg->wdata.active = true;
    1484        
    1485         ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg,
    1486             reply_received, true);
    1487        
    1488         sysarg_t rc;
    1489         async_wait_for((aid_t) msg, &rc);
    1490        
    1491         if (rc != EOK) {
    1492                 errno = rc;
    1493                 free(sess);
    1494                 return NULL;
    1495         }
    1496        
    1497         int phone = (int) IPC_GET_ARG5(result);
    1498        
    1499         if (phone < 0) {
    1500                 errno = phone;
    1501                 free(sess);
    1502                 return NULL;
    1503         }
    1504        
    1505         sess->mgmt = mgmt;
    1506         sess->phone = phone;
    1507         sess->arg1 = 0;
    1508         sess->arg2 = 0;
    1509         sess->arg3 = 0;
    1510        
    1511         list_initialize(&sess->exch_list);
    1512         fibril_mutex_initialize(&sess->mutex);
    1513         atomic_set(&sess->refcnt, 0);
    1514        
    1515         return sess;
    1516 }
    1517 
    1518 static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2,
    1519     sysarg_t arg3, sysarg_t arg4)
    1520 {
    1521         ipc_call_t result;
    1522        
    1523         amsg_t *msg = malloc(sizeof(amsg_t));
    1524         if (msg == NULL)
    1525                 return ENOENT;
    1526        
    1527         msg->done = false;
    1528         msg->dataptr = &result;
    1529        
    1530         msg->wdata.to_event.inlist = false;
    1531        
    1532         /*
    1533          * We may sleep in the next method,
    1534          * but it will use its own means
    1535          */
    1536         msg->wdata.active = true;
    1537        
    1538         ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4,
    1539             msg, reply_received, true);
    1540        
    1541         sysarg_t rc;
    1542         async_wait_for((aid_t) msg, &rc);
     1359/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
     1360 *
     1361 * Ask through phone for a new connection to some service.
     1362 *
     1363 * @param phone Phone handle used for contacting the other side.
     1364 * @param arg1  User defined argument.
     1365 * @param arg2  User defined argument.
     1366 * @param arg3  User defined argument.
     1367 *
     1368 * @return New phone handle on success or a negative error code.
     1369 *
     1370 */
     1371int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
     1372    sysarg_t arg3)
     1373{
     1374        sysarg_t newphid;
     1375        int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
     1376            NULL, NULL, NULL, NULL, &newphid);
    15431377       
    15441378        if (rc != EOK)
    15451379                return rc;
    15461380       
    1547         return (int) IPC_GET_ARG5(result);
    1548 }
    1549 
    1550 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
    1551  *
    1552  * Ask through for a new connection to some service.
    1553  *
    1554  * @param mgmt Exchange management style.
    1555  * @param exch Exchange for sending the message.
    1556  * @param arg1 User defined argument.
    1557  * @param arg2 User defined argument.
    1558  * @param arg3 User defined argument.
    1559  *
    1560  * @return New session on success or NULL on error.
    1561  *
    1562  */
    1563 async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch,
    1564     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
    1565 {
    1566         if (exch == NULL) {
    1567                 errno = ENOENT;
    1568                 return NULL;
    1569         }
    1570        
    1571         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    1572         if (sess == NULL) {
    1573                 errno = ENOMEM;
    1574                 return NULL;
    1575         }
    1576        
    1577         int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
    1578             0);
    1579        
    1580         if (phone < 0) {
    1581                 errno = phone;
    1582                 free(sess);
    1583                 return NULL;
    1584         }
    1585        
    1586         sess->mgmt = mgmt;
    1587         sess->phone = phone;
    1588         sess->arg1 = arg1;
    1589         sess->arg2 = arg2;
    1590         sess->arg3 = arg3;
    1591        
    1592         list_initialize(&sess->exch_list);
    1593         fibril_mutex_initialize(&sess->mutex);
    1594         atomic_set(&sess->refcnt, 0);
    1595        
    1596         return sess;
     1381        return newphid;
    15971382}
    15981383
     
    16021387 * success.
    16031388 *
    1604  * @param mgmt Exchange management style.
    1605  * @param exch Exchange for sending the message.
    1606  * @param arg1 User defined argument.
    1607  * @param arg2 User defined argument.
    1608  * @param arg3 User defined argument.
    1609  *
    1610  * @return New session on success or NULL on error.
    1611  *
    1612  */
    1613 async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch,
    1614     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
    1615 {
    1616         if (exch == NULL) {
    1617                 errno = ENOENT;
    1618                 return NULL;
    1619         }
    1620        
    1621         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    1622         if (sess == NULL) {
    1623                 errno = ENOMEM;
    1624                 return NULL;
    1625         }
    1626        
    1627         int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
    1628             IPC_FLAG_BLOCKING);
    1629        
    1630         if (phone < 0) {
    1631                 errno = phone;
    1632                 free(sess);
    1633                 return NULL;
    1634         }
    1635        
    1636         sess->mgmt = mgmt;
    1637         sess->phone = phone;
    1638         sess->arg1 = arg1;
    1639         sess->arg2 = arg2;
    1640         sess->arg3 = arg3;
    1641        
    1642         list_initialize(&sess->exch_list);
    1643         fibril_mutex_initialize(&sess->mutex);
    1644         atomic_set(&sess->refcnt, 0);
    1645        
    1646         return sess;
     1389 * @param phoneid Phone handle used for contacting the other side.
     1390 * @param arg1    User defined argument.
     1391 * @param arg2    User defined argument.
     1392 * @param arg3    User defined argument.
     1393 *
     1394 * @return New phone handle on success or a negative error code.
     1395 *
     1396 */
     1397int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
     1398    sysarg_t arg3)
     1399{
     1400        sysarg_t newphid;
     1401        int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
     1402            IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
     1403       
     1404        if (rc != EOK)
     1405                return rc;
     1406       
     1407        return newphid;
    16471408}
    16481409
     
    16501411 *
    16511412 */
    1652 async_sess_t *async_connect_kbox(task_id_t id)
    1653 {
    1654         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    1655         if (sess == NULL) {
    1656                 errno = ENOMEM;
    1657                 return NULL;
    1658         }
    1659        
    1660         int phone = ipc_connect_kbox(id);
    1661         if (phone < 0) {
    1662                 errno = phone;
    1663                 free(sess);
    1664                 return NULL;
    1665         }
    1666        
    1667         sess->mgmt = EXCHANGE_ATOMIC;
    1668         sess->phone = phone;
    1669         sess->arg1 = 0;
    1670         sess->arg2 = 0;
    1671         sess->arg3 = 0;
    1672        
    1673         list_initialize(&sess->exch_list);
    1674         fibril_mutex_initialize(&sess->mutex);
    1675         atomic_set(&sess->refcnt, 0);
    1676        
    1677         return sess;
    1678 }
    1679 
    1680 static int async_hangup_internal(int phone)
     1413int async_connect_kbox(task_id_t id)
     1414{
     1415        return ipc_connect_kbox(id);
     1416}
     1417
     1418/** Wrapper for ipc_hangup.
     1419 *
     1420 * @param phone Phone handle to hung up.
     1421 *
     1422 * @return Zero on success or a negative error code.
     1423 *
     1424 */
     1425int async_hangup(int phone)
    16811426{
    16821427        return ipc_hangup(phone);
    1683 }
    1684 
    1685 /** Wrapper for ipc_hangup.
    1686  *
    1687  * @param sess Session to hung up.
    1688  *
    1689  * @return Zero on success or a negative error code.
    1690  *
    1691  */
    1692 int async_hangup(async_sess_t *sess)
    1693 {
    1694         assert(sess);
    1695        
    1696         if (atomic_get(&sess->refcnt) > 0)
    1697                 return EBUSY;
    1698        
    1699         int rc = async_hangup_internal(sess->phone);
    1700         if (rc == EOK)
    1701                 free(sess);
    1702        
    1703         return rc;
    17041428}
    17051429
     
    17101434}
    17111435
    1712 /** Start new exchange in a session.
    1713  *
    1714  * @param session Session.
    1715  *
    1716  * @return New exchange or NULL on error.
    1717  *
    1718  */
    1719 async_exch_t *async_exchange_begin(async_sess_t *sess)
    1720 {
    1721         if (sess == NULL)
    1722                 return NULL;
    1723        
    1724         async_exch_t *exch;
    1725        
    1726         fibril_mutex_lock(&async_sess_mutex);
    1727        
    1728         if (!list_empty(&sess->exch_list)) {
    1729                 /*
    1730                  * There are inactive exchanges in the session.
    1731                  */
    1732                 exch = (async_exch_t *)
    1733                     list_get_instance(list_first(&sess->exch_list),
    1734                     async_exch_t, sess_link);
    1735                
    1736                 list_remove(&exch->sess_link);
    1737                 list_remove(&exch->global_link);
    1738         } else {
    1739                 /*
    1740                  * There are no available exchanges in the session.
    1741                  */
    1742                
    1743                 if ((sess->mgmt == EXCHANGE_ATOMIC) ||
    1744                     (sess->mgmt == EXCHANGE_SERIALIZE)) {
    1745                         exch = (async_exch_t *) malloc(sizeof(async_exch_t));
    1746                         if (exch != NULL) {
    1747                                 link_initialize(&exch->sess_link);
    1748                                 link_initialize(&exch->global_link);
    1749                                 exch->sess = sess;
    1750                                 exch->phone = sess->phone;
    1751                         }
    1752                 } else {  /* EXCHANGE_PARALLEL */
    1753                         /*
    1754                          * Make a one-time attempt to connect a new data phone.
    1755                          */
    1756                        
    1757                         int phone;
    1758                        
    1759 retry:
    1760                         phone = async_connect_me_to_internal(sess->phone, sess->arg1,
    1761                             sess->arg2, sess->arg3, 0);
    1762                         if (phone >= 0) {
    1763                                 exch = (async_exch_t *) malloc(sizeof(async_exch_t));
    1764                                 if (exch != NULL) {
    1765                                         link_initialize(&exch->sess_link);
    1766                                         link_initialize(&exch->global_link);
    1767                                         exch->sess = sess;
    1768                                         exch->phone = phone;
    1769                                 } else
    1770                                         async_hangup_internal(phone);
    1771                         } else if (!list_empty(&inactive_exch_list)) {
    1772                                 /*
    1773                                  * We did not manage to connect a new phone. But we
    1774                                  * can try to close some of the currently inactive
    1775                                  * connections in other sessions and try again.
    1776                                  */
    1777                                 exch = (async_exch_t *)
    1778                                     list_get_instance(list_first(&inactive_exch_list),
    1779                                     async_exch_t, global_link);
    1780                                
    1781                                 list_remove(&exch->sess_link);
    1782                                 list_remove(&exch->global_link);
    1783                                 async_hangup_internal(exch->phone);
    1784                                 free(exch);
    1785                                 goto retry;
    1786                         } else {
    1787                                 /*
    1788                                  * Wait for a phone to become available.
    1789                                  */
    1790                                 fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
    1791                                 goto retry;
    1792                         }
    1793                 }
    1794         }
    1795        
    1796         fibril_mutex_unlock(&async_sess_mutex);
    1797        
    1798         if (exch != NULL) {
    1799                 atomic_inc(&sess->refcnt);
    1800                
    1801                 if (sess->mgmt == EXCHANGE_SERIALIZE)
    1802                         fibril_mutex_lock(&sess->mutex);
    1803         }
    1804        
    1805         return exch;
    1806 }
    1807 
    1808 /** Finish an exchange.
    1809  *
    1810  * @param exch Exchange to finish.
    1811  *
    1812  */
    1813 void async_exchange_end(async_exch_t *exch)
    1814 {
    1815         if (exch == NULL)
    1816                 return;
    1817        
    1818         async_sess_t *sess = exch->sess;
    1819        
    1820         atomic_dec(&sess->refcnt);
    1821        
    1822         if (sess->mgmt == EXCHANGE_SERIALIZE)
    1823                 fibril_mutex_unlock(&sess->mutex);
    1824        
    1825         fibril_mutex_lock(&async_sess_mutex);
    1826        
    1827         list_append(&exch->sess_link, &sess->exch_list);
    1828         list_append(&exch->global_link, &inactive_exch_list);
    1829         fibril_condvar_signal(&avail_phone_cv);
    1830        
    1831         fibril_mutex_unlock(&async_sess_mutex);
    1832 }
    1833 
    18341436/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
    18351437 *
    1836  * @param exch  Exchange for sending the message.
    1837  * @param dst   Destination address space area base.
    1838  * @param size  Size of the destination address space area.
    1839  * @param arg   User defined argument.
    1840  * @param flags Storage for the received flags. Can be NULL.
     1438 * @param phoneid Phone that will be used to contact the receiving side.
     1439 * @param dst     Destination address space area base.
     1440 * @param size    Size of the destination address space area.
     1441 * @param arg     User defined argument.
     1442 * @param flags   Storage for the received flags. Can be NULL.
    18411443 *
    18421444 * @return Zero on success or a negative error code from errno.h.
    18431445 *
    18441446 */
    1845 int async_share_in_start(async_exch_t *exch, void *dst, size_t size,
    1846     sysarg_t arg, unsigned int *flags)
    1847 {
    1848         if (exch == NULL)
    1849                 return ENOENT;
    1850        
     1447int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
     1448    unsigned int *flags)
     1449{
    18511450        sysarg_t tmp_flags;
    1852         int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
     1451        int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
    18531452            (sysarg_t) size, arg, NULL, &tmp_flags);
    18541453       
     
    19081507/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
    19091508 *
    1910  * @param exch  Exchange for sending the message.
    1911  * @param src   Source address space area base address.
    1912  * @param flags Flags to be used for sharing. Bits can be only cleared.
     1509 * @param phoneid Phone that will be used to contact the receiving side.
     1510 * @param src     Source address space area base address.
     1511 * @param flags   Flags to be used for sharing. Bits can be only cleared.
    19131512 *
    19141513 * @return Zero on success or a negative error code from errno.h.
    19151514 *
    19161515 */
    1917 int async_share_out_start(async_exch_t *exch, void *src, unsigned int flags)
    1918 {
    1919         if (exch == NULL)
    1920                 return ENOENT;
    1921        
    1922         return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
     1516int async_share_out_start(int phoneid, void *src, unsigned int flags)
     1517{
     1518        return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
    19231519            (sysarg_t) flags);
    19241520}
     
    19731569}
    19741570
    1975 /** Start IPC_M_DATA_READ using the async framework.
    1976  *
    1977  * @param exch    Exchange for sending the message.
     1571/** Wrapper for IPC_M_DATA_READ calls using the async framework.
     1572 *
     1573 * @param phoneid Phone that will be used to contact the receiving side.
    19781574 * @param dst     Address of the beginning of the destination buffer.
    1979  * @param size    Size of the destination buffer (in bytes).
    1980  * @param dataptr Storage of call data (arg 2 holds actual data size).
    1981  *
    1982  * @return Hash of the sent message or 0 on error.
    1983  *
    1984  */
    1985 aid_t async_data_read(async_exch_t *exch, void *dst, size_t size,
    1986     ipc_call_t *dataptr)
    1987 {
    1988         return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst,
    1989             (sysarg_t) size, dataptr);
    1990 }
    1991 
    1992 /** Wrapper for IPC_M_DATA_READ calls using the async framework.
    1993  *
    1994  * @param exch Exchange for sending the message.
    1995  * @param dst  Address of the beginning of the destination buffer.
    1996  * @param size Size of the destination buffer.
     1575 * @param size    Size of the destination buffer.
     1576 * @param flags   Flags to control the data transfer.
    19971577 *
    19981578 * @return Zero on success or a negative error code from errno.h.
    19991579 *
    20001580 */
    2001 int async_data_read_start(async_exch_t *exch, void *dst, size_t size)
    2002 {
    2003         if (exch == NULL)
    2004                 return ENOENT;
    2005        
    2006         return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst,
    2007             (sysarg_t) size);
     1581int
     1582async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
     1583{
     1584        return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
     1585            (sysarg_t) size, (sysarg_t) flags);
    20081586}
    20091587
     
    20601638 *
    20611639 */
    2062 int async_data_read_forward_fast(async_exch_t *exch, sysarg_t imethod,
    2063     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
    2064     ipc_call_t *dataptr)
    2065 {
    2066         if (exch == NULL)
    2067                 return ENOENT;
    2068        
     1640int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
     1641    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
     1642{
    20691643        ipc_callid_t callid;
    20701644        if (!async_data_read_receive(&callid, NULL)) {
     
    20731647        }
    20741648       
    2075         aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
     1649        aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
    20761650            dataptr);
    20771651        if (msg == 0) {
     
    20801654        }
    20811655       
    2082         int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
     1656        int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
    20831657            IPC_FF_ROUTE_FROM_ME);
    20841658        if (retval != EOK) {
     
    20961670/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
    20971671 *
    2098  * @param exch Exchange for sending the message.
    2099  * @param src  Address of the beginning of the source buffer.
    2100  * @param size Size of the source buffer.
     1672 * @param phoneid Phone that will be used to contact the receiving side.
     1673 * @param src     Address of the beginning of the source buffer.
     1674 * @param size    Size of the source buffer.
     1675 * @param flags   Flags to control the data transfer.
    21011676 *
    21021677 * @return Zero on success or a negative error code from errno.h.
    21031678 *
    21041679 */
    2105 int async_data_write_start(async_exch_t *exch, const void *src, size_t size)
    2106 {
    2107         if (exch == NULL)
    2108                 return ENOENT;
    2109        
    2110         return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src,
    2111             (sysarg_t) size);
     1680int
     1681async_data_write_start_generic(int phoneid, const void *src, size_t size,
     1682    int flags)
     1683{
     1684        return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
     1685            (sysarg_t) size, (sysarg_t) flags);
    21121686}
    21131687
     
    21851759    size_t *received)
    21861760{
    2187         assert(data);
    2188        
    21891761        ipc_callid_t callid;
    21901762        size_t size;
     
    22541826 *
    22551827 */
    2256 int async_data_write_forward_fast(async_exch_t *exch, sysarg_t imethod,
    2257     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
    2258     ipc_call_t *dataptr)
    2259 {
    2260         if (exch == NULL)
    2261                 return ENOENT;
    2262        
     1828int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
     1829    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
     1830{
    22631831        ipc_callid_t callid;
    22641832        if (!async_data_write_receive(&callid, NULL)) {
     
    22671835        }
    22681836       
    2269         aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
     1837        aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
    22701838            dataptr);
    22711839        if (msg == 0) {
     
    22741842        }
    22751843       
    2276         int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
     1844        int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
    22771845            IPC_FF_ROUTE_FROM_ME);
    22781846        if (retval != EOK) {
     
    22881856}
    22891857
    2290 /** Wrapper for sending an exchange over different exchange for cloning
    2291  *
    2292  * @param exch       Exchange to be used for sending.
    2293  * @param clone_exch Exchange to be cloned.
    2294  *
    2295  */
    2296 int async_exchange_clone(async_exch_t *exch, async_exch_t *clone_exch)
    2297 {
    2298         return async_req_1_0(exch, IPC_M_CONNECTION_CLONE, clone_exch->phone);
    2299 }
    2300 
    2301 /** Wrapper for receiving the IPC_M_CONNECTION_CLONE calls.
    2302  *
    2303  * If the current call is IPC_M_CONNECTION_CLONE then a new
    2304  * async session is created for the accepted phone.
    2305  *
    2306  * @param mgmt Exchange management style.
    2307  *
    2308  * @return New async session or NULL on failure.
    2309  *
    2310  */
    2311 async_sess_t *async_clone_receive(exch_mgmt_t mgmt)
    2312 {
    2313         /* Accept the phone */
    2314         ipc_call_t call;
    2315         ipc_callid_t callid = async_get_call(&call);
    2316         int phone = (int) IPC_GET_ARG1(call);
    2317        
    2318         if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
    2319             (phone < 0)) {
    2320                 async_answer_0(callid, EINVAL);
    2321                 return NULL;
    2322         }
    2323        
    2324         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    2325         if (sess == NULL) {
    2326                 async_answer_0(callid, ENOMEM);
    2327                 return NULL;
    2328         }
    2329        
    2330         sess->mgmt = mgmt;
    2331         sess->phone = phone;
    2332         sess->arg1 = 0;
    2333         sess->arg2 = 0;
    2334         sess->arg3 = 0;
    2335        
    2336         list_initialize(&sess->exch_list);
    2337         fibril_mutex_initialize(&sess->mutex);
    2338         atomic_set(&sess->refcnt, 0);
    2339        
    2340         /* Acknowledge the cloned phone */
    2341         async_answer_0(callid, EOK);
    2342        
    2343         return sess;
    2344 }
    2345 
    2346 /** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls.
    2347  *
    2348  * If the current call is IPC_M_CONNECT_TO_ME then a new
    2349  * async session is created for the accepted phone.
    2350  *
    2351  * @param mgmt Exchange management style.
    2352  *
    2353  * @return New async session.
    2354  * @return NULL on failure.
    2355  *
    2356  */
    2357 async_sess_t *async_callback_receive(exch_mgmt_t mgmt)
    2358 {
    2359         /* Accept the phone */
    2360         ipc_call_t call;
    2361         ipc_callid_t callid = async_get_call(&call);
    2362         int phone = (int) IPC_GET_ARG5(call);
    2363        
    2364         if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) ||
    2365             (phone < 0)) {
    2366                 async_answer_0(callid, EINVAL);
    2367                 return NULL;
    2368         }
    2369        
    2370         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    2371         if (sess == NULL) {
    2372                 async_answer_0(callid, ENOMEM);
    2373                 return NULL;
    2374         }
    2375        
    2376         sess->mgmt = mgmt;
    2377         sess->phone = phone;
    2378         sess->arg1 = 0;
    2379         sess->arg2 = 0;
    2380         sess->arg3 = 0;
    2381        
    2382         list_initialize(&sess->exch_list);
    2383         fibril_mutex_initialize(&sess->mutex);
    2384         atomic_set(&sess->refcnt, 0);
    2385        
    2386         /* Acknowledge the connected phone */
    2387         async_answer_0(callid, EOK);
    2388        
    2389         return sess;
    2390 }
    2391 
    2392 /** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls.
    2393  *
    2394  * If the call is IPC_M_CONNECT_TO_ME then a new
    2395  * async session is created. However, the phone is
    2396  * not accepted automatically.
    2397  *
    2398  * @param mgmt   Exchange management style.
    2399  * @param call   Call data.
    2400  *
    2401  * @return New async session.
    2402  * @return NULL on failure.
    2403  * @return NULL if the call is not IPC_M_CONNECT_TO_ME.
    2404  *
    2405  */
    2406 async_sess_t *async_callback_receive_start(exch_mgmt_t mgmt, ipc_call_t *call)
    2407 {
    2408         int phone = (int) IPC_GET_ARG5(*call);
    2409        
    2410         if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) ||
    2411             (phone < 0))
    2412                 return NULL;
    2413        
    2414         async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    2415         if (sess == NULL)
    2416                 return NULL;
    2417        
    2418         sess->mgmt = mgmt;
    2419         sess->phone = phone;
    2420         sess->arg1 = 0;
    2421         sess->arg2 = 0;
    2422         sess->arg3 = 0;
    2423        
    2424         list_initialize(&sess->exch_list);
    2425         fibril_mutex_initialize(&sess->mutex);
    2426         atomic_set(&sess->refcnt, 0);
    2427        
    2428         return sess;
    2429 }
    2430 
    24311858/** @}
    24321859 */
Note: See TracChangeset for help on using the changeset viewer.