Ignore:
File:
1 edited

Legend:

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

    rc1c0184 r86d7bfa  
    4343 * framework will automatically take care of most synchronization problems.
    4444 *
    45  * Default semantics:
    46  * - async_send_*(): Send asynchronously. If the kernel refuses to send
    47  *                   more messages, [ try to get responses from kernel, if
    48  *                   nothing found, might try synchronous ]
    49  *
    5045 * Example of use (pseudo C):
    5146 *
     
    5853 *   int fibril1(void *arg)
    5954 *   {
    60  *     conn = ipc_connect_me_to();
     55 *     conn = async_connect_me_to();
    6156 *     c1 = async_send(conn);
    6257 *     c2 = async_send(conn);
     
    7772 *   {
    7873 *     if (want_refuse) {
    79  *       ipc_answer_0(icallid, ELIMIT);
     74 *       async_answer_0(icallid, ELIMIT);
    8075 *       return;
    8176 *     }
    82  *     ipc_answer_0(icallid, EOK);
     77 *     async_answer_0(icallid, EOK);
    8378 *
    8479 *     callid = async_get_call(&call);
    8580 *     somehow_handle_the_call(callid, call);
    86  *     ipc_answer_2(callid, 1, 2, 3);
     81 *     async_answer_2(callid, 1, 2, 3);
    8782 *
    8883 *     callid = async_get_call(&call);
     
    9287 */
    9388
     89#define LIBC_ASYNC_C_
     90#include <ipc/ipc.h>
     91#include <async.h>
     92#undef LIBC_ASYNC_C_
     93
    9494#include <futex.h>
    95 #include <async.h>
    96 #include <async_priv.h>
    9795#include <fibril.h>
    9896#include <stdio.h>
    9997#include <adt/hash_table.h>
    10098#include <adt/list.h>
    101 #include <ipc/ipc.h>
    10299#include <assert.h>
    103100#include <errno.h>
     
    105102#include <arch/barrier.h>
    106103#include <bool.h>
     104#include "private/async.h"
    107105
    108106atomic_t async_futex = FUTEX_INITIALIZER;
     
    124122
    125123/**
    126  * Structures of this type are used to group information about a call and a
    127  * message queue link.
     124 * Structures of this type are used to group information about
     125 * a call and about a message queue link.
    128126 */
    129127typedef struct {
     
    134132
    135133typedef struct {
     134        sysarg_t in_task_hash;
     135        link_t link;
     136        int refcnt;
     137        void *data;
     138} client_t;
     139
     140typedef struct {
    136141        awaiter_t wdata;
    137142       
     
    139144        link_t link;
    140145       
     146        /** Incoming client task hash. */
     147        sysarg_t in_task_hash;
    141148        /** Incoming phone hash. */
    142149        sysarg_t in_phone_hash;
     150       
     151        /** Link to the client tracking structure. */
     152        client_t *client;
    143153       
    144154        /** Messages that should be delivered to this fibril. */
     
    158168
    159169/** Identifier of the incoming connection handled by the current fibril. */
    160 fibril_local connection_t *FIBRIL_connection;
    161 
    162 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
    163 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
     170static fibril_local connection_t *FIBRIL_connection;
     171
     172static void *default_client_data_constructor(void)
     173{
     174        return NULL;
     175}
     176
     177static void default_client_data_destructor(void *data)
     178{
     179}
     180
     181static async_client_data_ctor_t async_client_data_create =
     182    default_client_data_constructor;
     183static async_client_data_dtor_t async_client_data_destroy =
     184    default_client_data_destructor;
     185
     186void async_set_client_data_constructor(async_client_data_ctor_t ctor)
     187{
     188        async_client_data_create = ctor;
     189}
     190
     191void async_set_client_data_destructor(async_client_data_dtor_t dtor)
     192{
     193        async_client_data_destroy = dtor;
     194}
     195
     196void *async_client_data_get(void)
     197{
     198        assert(FIBRIL_connection);
     199        return FIBRIL_connection->client->data;
     200}
     201
     202/** Default fibril function that gets called to handle new connection.
     203 *
     204 * This function is defined as a weak symbol - to be redefined in user code.
     205 *
     206 * @param callid Hash of the incoming call.
     207 * @param call   Data of the incoming call.
     208 *
     209 */
     210static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
     211{
     212        ipc_answer_0(callid, ENOENT);
     213}
    164214
    165215/**
     
    167217 */
    168218static async_client_conn_t client_connection = default_client_connection;
     219
     220/** Default fibril function that gets called to handle interrupt notifications.
     221 *
     222 * This function is defined as a weak symbol - to be redefined in user code.
     223 *
     224 * @param callid Hash of the incoming call.
     225 * @param call   Data of the incoming call.
     226 *
     227 */
     228static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
     229{
     230}
    169231
    170232/**
     
    174236static async_client_conn_t interrupt_received = default_interrupt_received;
    175237
     238static hash_table_t client_hash_table;
    176239static hash_table_t conn_hash_table;
    177240static LIST_INITIALIZE(timeout_list);
    178241
    179 #define CONN_HASH_TABLE_CHAINS  32
     242#define CLIENT_HASH_TABLE_BUCKETS  32
     243#define CONN_HASH_TABLE_BUCKETS    32
     244
     245static hash_index_t client_hash(unsigned long key[])
     246{
     247        assert(key);
     248        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
     249}
     250
     251static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
     252{
     253        client_t *client = hash_table_get_instance(item, client_t, link);
     254        return (key[0] == client->in_task_hash);
     255}
     256
     257static void client_remove(link_t *item)
     258{
     259}
     260
     261/** Operations for the client hash table. */
     262static hash_table_operations_t client_hash_table_ops = {
     263        .hash = client_hash,
     264        .compare = client_compare,
     265        .remove_callback = client_remove
     266};
    180267
    181268/** Compute hash into the connection hash table based on the source phone hash.
     
    186273 *
    187274 */
    188 static hash_index_t conn_hash(unsigned long *key)
     275static hash_index_t conn_hash(unsigned long key[])
    189276{
    190277        assert(key);
    191         return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS);
     278        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
    192279}
    193280
     
    203290static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
    204291{
    205         connection_t *hs = hash_table_get_instance(item, connection_t, link);
    206         return (key[0] == hs->in_phone_hash);
     292        connection_t *conn = hash_table_get_instance(item, connection_t, link);
     293        return (key[0] == conn->in_phone_hash);
    207294}
    208295
     
    219306        free(hash_table_get_instance(item, connection_t, link));
    220307}
    221 
    222308
    223309/** Operations for the connection hash table. */
     
    240326        link_t *tmp = timeout_list.next;
    241327        while (tmp != &timeout_list) {
    242                 awaiter_t *cur;
    243                
    244                 cur = list_get_instance(tmp, awaiter_t, to_event.link);
     328                awaiter_t *cur
     329                    = list_get_instance(tmp, awaiter_t, to_event.link);
     330               
    245331                if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires))
    246332                        break;
     333               
    247334                tmp = tmp->next;
    248335        }
     
    261348 *
    262349 * @return False if the call doesn't match any connection.
    263  *         True if the call was passed to the respective connection fibril.
     350 * @return True if the call was passed to the respective connection fibril.
    264351 *
    265352 */
     
    352439       
    353440        fid_t fid = fibril_create(notification_fibril, msg);
     441        if (fid == 0) {
     442                free(msg);
     443                futex_up(&async_futex);
     444                return false;
     445        }
     446       
    354447        fibril_add_ready(fid);
    355448       
     
    398491                         * the first IPC_M_PHONE_HUNGUP call and continues to
    399492                         * call async_get_call_timeout(). Repeat
    400                          * IPC_M_PHONE_HUNGUP until the caller notices. 
     493                         * IPC_M_PHONE_HUNGUP until the caller notices.
    401494                         */
    402495                        memset(call, 0, sizeof(ipc_call_t));
     
    405498                        return conn->close_callid;
    406499                }
    407 
     500               
    408501                if (usecs)
    409502                        async_insert_timeout(&conn->wdata);
     
    443536}
    444537
    445 /** Default fibril function that gets called to handle new connection.
    446  *
    447  * This function is defined as a weak symbol - to be redefined in user code.
    448  *
    449  * @param callid Hash of the incoming call.
    450  * @param call   Data of the incoming call.
    451  *
    452  */
    453 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
    454 {
    455         ipc_answer_0(callid, ENOENT);
    456 }
    457 
    458 /** Default fibril function that gets called to handle interrupt notifications.
    459  *
    460  * This function is defined as a weak symbol - to be redefined in user code.
    461  *
    462  * @param callid Hash of the incoming call.
    463  * @param call   Data of the incoming call.
    464  *
    465  */
    466 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
    467 {
    468 }
    469 
    470538/** Wrapper for client connection fibril.
    471539 *
     
    481549{
    482550        /*
    483          * Setup fibril-local connection pointer and call client_connection().
    484          *
     551         * Setup fibril-local connection pointer.
    485552         */
    486553        FIBRIL_connection = (connection_t *) arg;
     554       
     555        futex_down(&async_futex);
     556       
     557        /*
     558         * Add our reference for the current connection in the client task
     559         * tracking structure. If this is the first reference, create and
     560         * hash in a new tracking structure.
     561         */
     562       
     563        unsigned long key = FIBRIL_connection->in_task_hash;
     564        link_t *lnk = hash_table_find(&client_hash_table, &key);
     565       
     566        client_t *client;
     567       
     568        if (lnk) {
     569                client = hash_table_get_instance(lnk, client_t, link);
     570                client->refcnt++;
     571        } else {
     572                client = malloc(sizeof(client_t));
     573                if (!client) {
     574                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
     575                        futex_up(&async_futex);
     576                        return 0;
     577                }
     578               
     579                client->in_task_hash = FIBRIL_connection->in_task_hash;
     580               
     581                async_serialize_start();
     582                client->data = async_client_data_create();
     583                async_serialize_end();
     584               
     585                client->refcnt = 1;
     586                hash_table_insert(&client_hash_table, &key, &client->link);
     587        }
     588       
     589        futex_up(&async_futex);
     590       
     591        FIBRIL_connection->client = client;
     592       
     593        /*
     594         * Call the connection handler function.
     595         */
    487596        FIBRIL_connection->cfibril(FIBRIL_connection->callid,
    488597            &FIBRIL_connection->call);
    489598       
    490         /* Remove myself from the connection hash table */
     599        /*
     600         * Remove the reference for this client task connection.
     601         */
     602        bool destroy;
     603       
    491604        futex_down(&async_futex);
    492         unsigned long key = FIBRIL_connection->in_phone_hash;
     605       
     606        if (--client->refcnt == 0) {
     607                hash_table_remove(&client_hash_table, &key, 1);
     608                destroy = true;
     609        } else
     610                destroy = false;
     611       
     612        futex_up(&async_futex);
     613       
     614        if (destroy) {
     615                if (client->data)
     616                        async_client_data_destroy(client->data);
     617               
     618                free(client);
     619        }
     620       
     621        /*
     622         * Remove myself from the connection hash table.
     623         */
     624        futex_down(&async_futex);
     625        key = FIBRIL_connection->in_phone_hash;
    493626        hash_table_remove(&conn_hash_table, &key, 1);
    494627        futex_up(&async_futex);
    495628       
    496         /* Answer all remaining messages with EHANGUP */
     629        /*
     630         * Answer all remaining messages with EHANGUP.
     631         */
    497632        while (!list_empty(&FIBRIL_connection->msg_queue)) {
    498                 msg_t *msg;
    499                
    500                 msg = list_get_instance(FIBRIL_connection->msg_queue.next,
    501                     msg_t, link);
     633                msg_t *msg =
     634                    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
     635                    link);
     636               
    502637                list_remove(&msg->link);
    503638                ipc_answer_0(msg->callid, EHANGUP);
     
    505640        }
    506641       
     642        /*
     643         * If the connection was hung-up, answer the last call,
     644         * i.e. IPC_M_PHONE_HUNGUP.
     645         */
    507646        if (FIBRIL_connection->close_callid)
    508647                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
     
    517656 * particular fibrils.
    518657 *
     658 * @param in_task_hash  Identification of the incoming connection.
    519659 * @param in_phone_hash Identification of the incoming connection.
    520660 * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
     
    529669 *
    530670 */
    531 fid_t async_new_connection(sysarg_t in_phone_hash, ipc_callid_t callid,
    532     ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *))
     671fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
     672    ipc_callid_t callid, ipc_call_t *call,
     673    void (*cfibril)(ipc_callid_t, ipc_call_t *))
    533674{
    534675        connection_t *conn = malloc(sizeof(*conn));
     
    536677                if (callid)
    537678                        ipc_answer_0(callid, ENOMEM);
     679               
    538680                return (uintptr_t) NULL;
    539681        }
    540682       
     683        conn->in_task_hash = in_task_hash;
    541684        conn->in_phone_hash = in_phone_hash;
    542685        list_initialize(&conn->msg_queue);
     
    552695        conn->wdata.fid = fibril_create(connection_fibril, conn);
    553696       
    554         if (!conn->wdata.fid) {
     697        if (conn->wdata.fid == 0) {
    555698                free(conn);
     699               
    556700                if (callid)
    557701                        ipc_answer_0(callid, ENOMEM);
     702               
    558703                return (uintptr_t) NULL;
    559704        }
     
    582727static void handle_call(ipc_callid_t callid, ipc_call_t *call)
    583728{
    584         /* Unrouted call - do some default behaviour */
     729        /* Unrouted call - take some default action */
    585730        if ((callid & IPC_CALLID_NOTIFICATION)) {
    586731                process_notification(callid, call);
    587                 goto out;
     732                return;
    588733        }
    589734       
     
    591736        case IPC_M_CONNECT_ME:
    592737        case IPC_M_CONNECT_ME_TO:
    593                 /* Open new connection with fibril etc. */
    594                 async_new_connection(IPC_GET_ARG5(*call), callid, call,
    595                     client_connection);
    596                 goto out;
     738                /* Open new connection with fibril, etc. */
     739                async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
     740                    callid, call, client_connection);
     741                return;
    597742        }
    598743       
    599744        /* Try to route the call through the connection hash table */
    600745        if (route_call(callid, call))
    601                 goto out;
     746                return;
    602747       
    603748        /* Unknown call from unknown phone - hang it up */
    604749        ipc_answer_0(callid, EHANGUP);
    605         return;
    606        
    607 out:
    608         ;
    609750}
    610751
     
    619760        link_t *cur = timeout_list.next;
    620761        while (cur != &timeout_list) {
    621                 awaiter_t *waiter;
    622                
    623                 waiter = list_get_instance(cur, awaiter_t, to_event.link);
     762                awaiter_t *waiter =
     763                    list_get_instance(cur, awaiter_t, to_event.link);
     764               
    624765                if (tv_gt(&waiter->to_event.expires, &tv))
    625766                        break;
    626 
     767               
    627768                cur = cur->next;
    628 
     769               
    629770                list_remove(&waiter->to_event.link);
    630771                waiter->to_event.inlist = false;
     
    653794        while (true) {
    654795                if (fibril_switch(FIBRIL_FROM_MANAGER)) {
    655                         futex_up(&async_futex); 
     796                        futex_up(&async_futex);
    656797                        /*
    657798                         * async_futex is always held when entering a manager
     
    676817                                continue;
    677818                        } else
    678                                 timeout = tv_sub(&waiter->to_event.expires,
    679                                     &tv);
     819                                timeout = tv_sub(&waiter->to_event.expires, &tv);
    680820                } else
    681821                        timeout = SYNCH_NO_TIMEOUT;
    682822               
    683823                futex_up(&async_futex);
    684 
     824               
    685825                atomic_inc(&threads_in_ipc_wait);
    686826               
     
    690830               
    691831                atomic_dec(&threads_in_ipc_wait);
    692 
     832               
    693833                if (!callid) {
    694834                        handle_expired_timeouts();
     
    729869{
    730870        fid_t fid = fibril_create(async_manager_fibril, NULL);
    731         fibril_add_manager(fid);
     871        if (fid != 0)
     872                fibril_add_manager(fid);
    732873}
    733874
     
    740881/** Initialize the async framework.
    741882 *
    742  * @return Zero on success or an error code.
    743  */
    744 int __async_init(void)
    745 {
    746         if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1,
    747             &conn_hash_table_ops)) {
    748                 printf("%s: Cannot create async hash table\n", "libc");
    749                 return ENOMEM;
    750         }
    751 
    752         _async_sess_init();
    753        
    754         return 0;
     883 */
     884void __async_init(void)
     885{
     886        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
     887            &client_hash_table_ops))
     888                abort();
     889       
     890        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
     891            &conn_hash_table_ops))
     892                abort();
    755893}
    756894
     
    765903 * @param retval Value returned in the answer.
    766904 * @param data   Call data of the answer.
     905 *
    767906 */
    768907static void reply_received(void *arg, int retval, ipc_call_t *data)
     
    812951    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    813952{
    814         amsg_t *msg = malloc(sizeof(*msg));
     953        amsg_t *msg = malloc(sizeof(amsg_t));
    815954       
    816955        if (!msg)
     
    821960       
    822961        msg->wdata.to_event.inlist = false;
    823         /* We may sleep in the next method, but it will use its own mechanism */
     962       
     963        /*
     964         * We may sleep in the next method,
     965         * but it will use its own means
     966         */
    824967        msg->wdata.active = true;
    825968       
     
    852995    ipc_call_t *dataptr)
    853996{
    854         amsg_t *msg = malloc(sizeof(*msg));
     997        amsg_t *msg = malloc(sizeof(amsg_t));
    855998       
    856999        if (!msg)
     
    8611004       
    8621005        msg->wdata.to_event.inlist = false;
    863         /* We may sleep in next method, but it will use its own mechanism */
     1006       
     1007        /*
     1008         * We may sleep in the next method,
     1009         * but it will use its own means
     1010         */
    8641011        msg->wdata.active = true;
    8651012       
     
    9601107void async_usleep(suseconds_t timeout)
    9611108{
    962         amsg_t *msg = malloc(sizeof(*msg));
     1109        amsg_t *msg = malloc(sizeof(amsg_t));
    9631110       
    9641111        if (!msg)
     
    11031250}
    11041251
     1252void async_msg_0(int phone, sysarg_t imethod)
     1253{
     1254        ipc_call_async_0(phone, imethod, NULL, NULL, true);
     1255}
     1256
     1257void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
     1258{
     1259        ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
     1260}
     1261
     1262void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
     1263{
     1264        ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
     1265}
     1266
     1267void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     1268    sysarg_t arg3)
     1269{
     1270        ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
     1271}
     1272
     1273void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     1274    sysarg_t arg3, sysarg_t arg4)
     1275{
     1276        ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
     1277            true);
     1278}
     1279
     1280void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     1281    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
     1282{
     1283        ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
     1284            NULL, true);
     1285}
     1286
     1287sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval)
     1288{
     1289        return ipc_answer_0(callid, retval);
     1290}
     1291
     1292sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1)
     1293{
     1294        return ipc_answer_1(callid, retval, arg1);
     1295}
     1296
     1297sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     1298    sysarg_t arg2)
     1299{
     1300        return ipc_answer_2(callid, retval, arg1, arg2);
     1301}
     1302
     1303sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     1304    sysarg_t arg2, sysarg_t arg3)
     1305{
     1306        return ipc_answer_3(callid, retval, arg1, arg2, arg3);
     1307}
     1308
     1309sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     1310    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
     1311{
     1312        return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4);
     1313}
     1314
     1315sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     1316    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
     1317{
     1318        return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5);
     1319}
     1320
     1321int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     1322    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
     1323{
     1324        return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
     1325}
     1326
     1327int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     1328    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
     1329    unsigned int mode)
     1330{
     1331        return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
     1332            arg5, mode);
     1333}
     1334
     1335/** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework.
     1336 *
     1337 * Ask through phone for a new connection to some service.
     1338 *
     1339 * @param phone           Phone handle used for contacting the other side.
     1340 * @param arg1            User defined argument.
     1341 * @param arg2            User defined argument.
     1342 * @param arg3            User defined argument.
     1343 * @param client_receiver Connection handing routine.
     1344 *
     1345 * @return New phone handle on success or a negative error code.
     1346 *
     1347 */
     1348int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
     1349    sysarg_t arg3, async_client_conn_t client_receiver)
     1350{
     1351        sysarg_t task_hash;
     1352        sysarg_t phone_hash;
     1353        int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
     1354            NULL, NULL, NULL, &task_hash, &phone_hash);
     1355        if (rc != EOK)
     1356                return rc;
     1357       
     1358        if (client_receiver != NULL)
     1359                async_new_connection(task_hash, phone_hash, 0, NULL,
     1360                    client_receiver);
     1361       
     1362        return EOK;
     1363}
     1364
    11051365/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
    1106  * 
     1366 *
    11071367 * Ask through phone for a new connection to some service.
    11081368 *
    1109  * @param phoneid       Phone handle used for contacting the other side.
    1110  * @param arg1          User defined argument.
    1111  * @param arg2          User defined argument.
    1112  * @param arg3          User defined argument.
    1113  *
    1114  * @return              New phone handle on success or a negative error code.
    1115  */
    1116 int
    1117 async_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
    1118 {
    1119         int rc;
     1369 * @param phone Phone handle used for contacting the other side.
     1370 * @param arg1  User defined argument.
     1371 * @param arg2  User defined argument.
     1372 * @param arg3  User defined argument.
     1373 *
     1374 * @return New phone handle on success or a negative error code.
     1375 *
     1376 */
     1377int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
     1378    sysarg_t arg3)
     1379{
    11201380        sysarg_t newphid;
    1121 
    1122         rc = async_req_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, NULL,
    1123             NULL, NULL, NULL, &newphid);
    1124        
    1125         if (rc != EOK) 
     1381        int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
     1382            NULL, NULL, NULL, NULL, &newphid);
     1383       
     1384        if (rc != EOK)
    11261385                return rc;
    1127 
     1386       
    11281387        return newphid;
    11291388}
    11301389
    11311390/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
    1132  * 
     1391 *
    11331392 * Ask through phone for a new connection to some service and block until
    11341393 * success.
    11351394 *
    1136  * @param phoneid       Phone handle used for contacting the other side.
    1137  * @param arg1          User defined argument.
    1138  * @param arg2          User defined argument.
    1139  * @param arg3          User defined argument.
    1140  *
    1141  * @return              New phone handle on success or a negative error code.
    1142  */
    1143 int
    1144 async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
     1395 * @param phoneid Phone handle used for contacting the other side.
     1396 * @param arg1    User defined argument.
     1397 * @param arg2    User defined argument.
     1398 * @param arg3    User defined argument.
     1399 *
     1400 * @return New phone handle on success or a negative error code.
     1401 *
     1402 */
     1403int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
    11451404    sysarg_t arg3)
    11461405{
    1147         int rc;
    11481406        sysarg_t newphid;
    1149 
    1150         rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
     1407        int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
    11511408            IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
    11521409       
    1153         if (rc != EOK) 
     1410        if (rc != EOK)
    11541411                return rc;
    1155 
     1412       
    11561413        return newphid;
    11571414}
    11581415
    1159 /** Wrapper for making IPC_M_SHARE_IN calls using the async framework.
    1160  *
    1161  * @param phoneid       Phone that will be used to contact the receiving side.
    1162  * @param dst           Destination address space area base.
    1163  * @param size          Size of the destination address space area.
    1164  * @param arg           User defined argument.
    1165  * @param flags         Storage where the received flags will be stored. Can be
    1166  *                      NULL.
    1167  *
    1168  * @return              Zero on success or a negative error code from errno.h.
     1416/** Connect to a task specified by id.
     1417 *
     1418 */
     1419int async_connect_kbox(task_id_t id)
     1420{
     1421        return ipc_connect_kbox(id);
     1422}
     1423
     1424/** Wrapper for ipc_hangup.
     1425 *
     1426 * @param phone Phone handle to hung up.
     1427 *
     1428 * @return Zero on success or a negative error code.
     1429 *
     1430 */
     1431int async_hangup(int phone)
     1432{
     1433        return ipc_hangup(phone);
     1434}
     1435
     1436/** Interrupt one thread of this task from waiting for IPC. */
     1437void async_poke(void)
     1438{
     1439        ipc_poke();
     1440}
     1441
     1442/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
     1443 *
     1444 * @param phoneid Phone that will be used to contact the receiving side.
     1445 * @param dst     Destination address space area base.
     1446 * @param size    Size of the destination address space area.
     1447 * @param arg     User defined argument.
     1448 * @param flags   Storage for the received flags. Can be NULL.
     1449 *
     1450 * @return Zero on success or a negative error code from errno.h.
     1451 *
    11691452 */
    11701453int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
    1171     int *flags)
    1172 {
    1173         int res;
     1454    unsigned int *flags)
     1455{
    11741456        sysarg_t tmp_flags;
    1175         res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
     1457        int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
    11761458            (sysarg_t) size, arg, NULL, &tmp_flags);
     1459       
    11771460        if (flags)
    1178                 *flags = tmp_flags;
     1461                *flags = (unsigned int) tmp_flags;
     1462       
    11791463        return res;
    11801464}
     
    11821466/** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework.
    11831467 *
    1184  * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
    1185  * so that the user doesn't have to remember the meaning of each IPC argument.
     1468 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN
     1469 * calls so that the user doesn't have to remember the meaning of each IPC
     1470 * argument.
    11861471 *
    11871472 * So far, this wrapper is to be used from within a connection fibril.
    11881473 *
    1189  * @param callid        Storage where the hash of the IPC_M_SHARE_IN call will
    1190  *                      be stored.
    1191  * @param size          Destination address space area size.   
    1192  *
    1193  * @return              Non-zero on success, zero on failure.
    1194  */
    1195 int async_share_in_receive(ipc_callid_t *callid, size_t *size)
    1196 {
    1197         ipc_call_t data;
    1198        
     1474 * @param callid Storage for the hash of the IPC_M_SHARE_IN call.
     1475 * @param size   Destination address space area size.
     1476 *
     1477 * @return True on success, false on failure.
     1478 *
     1479 */
     1480bool async_share_in_receive(ipc_callid_t *callid, size_t *size)
     1481{
    11991482        assert(callid);
    12001483        assert(size);
    1201 
     1484       
     1485        ipc_call_t data;
    12021486        *callid = async_get_call(&data);
     1487       
    12031488        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN)
    1204                 return 0;
     1489                return false;
     1490       
    12051491        *size = (size_t) IPC_GET_ARG2(data);
    1206         return 1;
     1492        return true;
    12071493}
    12081494
    12091495/** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
    12101496 *
    1211  * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
    1212  * so that the user doesn't have to remember the meaning of each IPC argument.
    1213  *
    1214  * @param callid        Hash of the IPC_M_DATA_READ call to answer.
    1215  * @param src           Source address space base.
    1216  * @param flags         Flags to be used for sharing. Bits can be only cleared.
    1217  *
    1218  * @return              Zero on success or a value from @ref errno.h on failure.
    1219  */
    1220 int async_share_in_finalize(ipc_callid_t callid, void *src, int flags)
     1497 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
     1498 * calls so that the user doesn't have to remember the meaning of each IPC
     1499 * argument.
     1500 *
     1501 * @param callid Hash of the IPC_M_DATA_READ call to answer.
     1502 * @param src    Source address space base.
     1503 * @param flags  Flags to be used for sharing. Bits can be only cleared.
     1504 *
     1505 * @return Zero on success or a value from @ref errno.h on failure.
     1506 *
     1507 */
     1508int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
    12211509{
    12221510        return ipc_share_in_finalize(callid, src, flags);
    12231511}
    12241512
    1225 /** Wrapper for making IPC_M_SHARE_OUT calls using the async framework.
    1226  *
    1227  * @param phoneid       Phone that will be used to contact the receiving side.
    1228  * @param src           Source address space area base address.
    1229  * @param flags         Flags to be used for sharing. Bits can be only cleared.
    1230  *
    1231  * @return              Zero on success or a negative error code from errno.h.
    1232  */
    1233 int async_share_out_start(int phoneid, void *src, int flags)
     1513/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
     1514 *
     1515 * @param phoneid Phone that will be used to contact the receiving side.
     1516 * @param src     Source address space area base address.
     1517 * @param flags   Flags to be used for sharing. Bits can be only cleared.
     1518 *
     1519 * @return Zero on success or a negative error code from errno.h.
     1520 *
     1521 */
     1522int async_share_out_start(int phoneid, void *src, unsigned int flags)
    12341523{
    12351524        return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
     
    12391528/** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework.
    12401529 *
    1241  * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
    1242  * so that the user doesn't have to remember the meaning of each IPC argument.
     1530 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT
     1531 * calls so that the user doesn't have to remember the meaning of each IPC
     1532 * argument.
    12431533 *
    12441534 * So far, this wrapper is to be used from within a connection fibril.
    12451535 *
    1246  * @param callid        Storage where the hash of the IPC_M_SHARE_OUT call will
    1247  *                      be stored.
    1248  * @param size          Storage where the source address space area size will be
    1249  *                      stored.
    1250  * @param flags         Storage where the sharing flags will be stored.
    1251  *
    1252  * @return              Non-zero on success, zero on failure.
    1253  */
    1254 int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
    1255 {
    1256         ipc_call_t data;
    1257        
     1536 * @param callid Storage for the hash of the IPC_M_SHARE_OUT call.
     1537 * @param size   Storage for the source address space area size.
     1538 * @param flags  Storage for the sharing flags.
     1539 *
     1540 * @return True on success, false on failure.
     1541 *
     1542 */
     1543bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags)
     1544{
    12581545        assert(callid);
    12591546        assert(size);
    12601547        assert(flags);
    1261 
     1548       
     1549        ipc_call_t data;
    12621550        *callid = async_get_call(&data);
     1551       
    12631552        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT)
    1264                 return 0;
     1553                return false;
     1554       
    12651555        *size = (size_t) IPC_GET_ARG2(data);
    1266         *flags = (int) IPC_GET_ARG3(data);
    1267         return 1;
     1556        *flags = (unsigned int) IPC_GET_ARG3(data);
     1557        return true;
    12681558}
    12691559
    12701560/** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework.
    12711561 *
    1272  * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
    1273  * so that the user doesn't have to remember the meaning of each IPC argument.
    1274  *
    1275  * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
    1276  * @param dst           Destination address space area base address.   
    1277  *
    1278  * @return              Zero on success or a value from @ref errno.h on failure.
     1562 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT
     1563 * calls so that the user doesn't have to remember the meaning of each IPC
     1564 * argument.
     1565 *
     1566 * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
     1567 * @param dst    Destination address space area base address.
     1568 *
     1569 * @return Zero on success or a value from @ref errno.h on failure.
     1570 *
    12791571 */
    12801572int async_share_out_finalize(ipc_callid_t callid, void *dst)
     
    12831575}
    12841576
    1285 
    1286 /** Wrapper for making IPC_M_DATA_READ calls using the async framework.
    1287  *
    1288  * @param phoneid       Phone that will be used to contact the receiving side.
    1289  * @param dst           Address of the beginning of the destination buffer.
    1290  * @param size          Size of the destination buffer.
    1291  *
    1292  * @return              Zero on success or a negative error code from errno.h.
     1577/** Wrapper for IPC_M_DATA_READ calls using the async framework.
     1578 *
     1579 * @param phoneid Phone that will be used to contact the receiving side.
     1580 * @param dst     Address of the beginning of the destination buffer.
     1581 * @param size    Size of the destination buffer.
     1582 *
     1583 * @return Zero on success or a negative error code from errno.h.
     1584 *
    12931585 */
    12941586int async_data_read_start(int phoneid, void *dst, size_t size)
     
    13001592/** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework.
    13011593 *
    1302  * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
    1303  * so that the user doesn't have to remember the meaning of each IPC argument.
     1594 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ
     1595 * calls so that the user doesn't have to remember the meaning of each IPC
     1596 * argument.
    13041597 *
    13051598 * So far, this wrapper is to be used from within a connection fibril.
    13061599 *
    1307  * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
    1308  *                      be stored.
    1309  * @param size          Storage where the maximum size will be stored. Can be
    1310  *                      NULL.
    1311  *
    1312  * @return              Non-zero on success, zero on failure.
    1313  */
    1314 int async_data_read_receive(ipc_callid_t *callid, size_t *size)
    1315 {
     1600 * @param callid Storage for the hash of the IPC_M_DATA_READ.
     1601 * @param size   Storage for the maximum size. Can be NULL.
     1602 *
     1603 * @return True on success, false on failure.
     1604 *
     1605 */
     1606bool async_data_read_receive(ipc_callid_t *callid, size_t *size)
     1607{
     1608        assert(callid);
     1609       
    13161610        ipc_call_t data;
    1317        
    1318         assert(callid);
    1319 
    13201611        *callid = async_get_call(&data);
     1612       
    13211613        if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ)
    1322                 return 0;
     1614                return false;
     1615       
    13231616        if (size)
    13241617                *size = (size_t) IPC_GET_ARG2(data);
    1325         return 1;
     1618       
     1619        return true;
    13261620}
    13271621
    13281622/** Wrapper for answering the IPC_M_DATA_READ calls using the async framework.
    13291623 *
    1330  * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
    1331  * so that the user doesn't have to remember the meaning of each IPC argument.
    1332  *
    1333  * @param callid        Hash of the IPC_M_DATA_READ call to answer.
    1334  * @param src           Source address for the IPC_M_DATA_READ call.
    1335  * @param size          Size for the IPC_M_DATA_READ call. Can be smaller than
    1336  *                      the maximum size announced by the sender.
    1337  *
    1338  * @return              Zero on success or a value from @ref errno.h on failure.
     1624 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
     1625 * calls so that the user doesn't have to remember the meaning of each IPC
     1626 * argument.
     1627 *
     1628 * @param callid Hash of the IPC_M_DATA_READ call to answer.
     1629 * @param src    Source address for the IPC_M_DATA_READ call.
     1630 * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
     1631 *               the maximum size announced by the sender.
     1632 *
     1633 * @return Zero on success or a value from @ref errno.h on failure.
     1634 *
    13391635 */
    13401636int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
     
    13441640
    13451641/** Wrapper for forwarding any read request
    1346  *
    13471642 *
    13481643 */
     
    13771672}
    13781673
    1379 /** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
     1674/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
    13801675 *
    13811676 * @param phoneid Phone that will be used to contact the receiving side.
     
    13941689/** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework.
    13951690 *
    1396  * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
    1397  * so that the user doesn't have to remember the meaning of each IPC argument.
     1691 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE
     1692 * calls so that the user doesn't have to remember the meaning of each IPC
     1693 * argument.
    13981694 *
    13991695 * So far, this wrapper is to be used from within a connection fibril.
    14001696 *
    1401  * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will
    1402  *               be stored.
    1403  * @param size   Storage where the suggested size will be stored. May be
    1404  *               NULL
    1405  *
    1406  * @return Non-zero on success, zero on failure.
    1407  *
    1408  */
    1409 int async_data_write_receive(ipc_callid_t *callid, size_t *size)
    1410 {
     1697 * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
     1698 * @param size   Storage for the suggested size. May be NULL.
     1699 *
     1700 * @return True on success, false on failure.
     1701 *
     1702 */
     1703bool async_data_write_receive(ipc_callid_t *callid, size_t *size)
     1704{
     1705        assert(callid);
     1706       
    14111707        ipc_call_t data;
    1412        
    1413         assert(callid);
    1414        
    14151708        *callid = async_get_call(&data);
     1709       
    14161710        if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE)
    1417                 return 0;
     1711                return false;
    14181712       
    14191713        if (size)
    14201714                *size = (size_t) IPC_GET_ARG2(data);
    14211715       
    1422         return 1;
     1716        return true;
    14231717}
    14241718
    14251719/** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework.
    14261720 *
    1427  * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
    1428  * so that the user doesn't have to remember the meaning of each IPC argument.
     1721 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE
     1722 * calls so that the user doesn't have to remember the meaning of each IPC
     1723 * argument.
    14291724 *
    14301725 * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
     
    15221817 *
    15231818 */
    1524 void async_data_write_void(const int retval)
     1819void async_data_write_void(sysarg_t retval)
    15251820{
    15261821        ipc_callid_t callid;
     
    15301825
    15311826/** Wrapper for forwarding any data that is about to be received
    1532  *
    15331827 *
    15341828 */
Note: See TracChangeset for help on using the changeset viewer.