Changeset 4687fcd4 in mainline for uspace/lib/c/generic/async.c


Ignore:
Timestamp:
2011-01-29T10:19:04Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
72e19f50
Parents:
67a1b78 (diff), a09128c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Changes from devel, break stuff.

File:
1 edited

Legend:

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

    r67a1b78 r4687fcd4  
    134134
    135135typedef struct {
     136        sysarg_t in_task_hash;
     137        link_t link;
     138        int refcnt;
     139        void *data;
     140} client_t;
     141
     142typedef struct {
    136143        awaiter_t wdata;
    137144       
     
    139146        link_t link;
    140147       
     148        /** Incoming client task hash. */
     149        sysarg_t in_task_hash;
    141150        /** Incoming phone hash. */
    142151        sysarg_t in_phone_hash;
    143152       
     153        /** Link to the client tracking structure. */
     154        client_t *client;
     155
    144156        /** Messages that should be delivered to this fibril. */
    145157        link_t msg_queue;
     
    160172fibril_local connection_t *FIBRIL_connection;
    161173
     174static void *default_client_data_constructor(void)
     175{
     176        return NULL;
     177}
     178
     179static void default_client_data_destructor(void *data)
     180{
     181}
     182
     183static async_client_data_ctor_t async_client_data_create =
     184    default_client_data_constructor;
     185static async_client_data_dtor_t async_client_data_destroy =
     186    default_client_data_destructor;
     187
     188void async_set_client_data_constructor(async_client_data_ctor_t ctor)
     189{
     190        async_client_data_create = ctor;
     191}
     192
     193void async_set_client_data_destructor(async_client_data_dtor_t dtor)
     194{
     195        async_client_data_destroy = dtor;
     196}
     197
     198void *async_client_data_get(void)
     199{
     200        assert(FIBRIL_connection);
     201
     202        return FIBRIL_connection->client->data;
     203}
     204
    162205static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
    163206static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
     
    174217static async_client_conn_t interrupt_received = default_interrupt_received;
    175218
     219static hash_table_t client_hash_table;
    176220static hash_table_t conn_hash_table;
    177221static LIST_INITIALIZE(timeout_list);
    178222
    179 #define CONN_HASH_TABLE_CHAINS  32
     223#define CLIENT_HASH_TABLE_BUCKETS       32
     224#define CONN_HASH_TABLE_BUCKETS         32
     225
     226static hash_index_t client_hash(unsigned long *key)
     227{
     228        assert(key);
     229        return (((*key) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
     230}
     231
     232static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
     233{
     234        client_t *cl = hash_table_get_instance(item, client_t, link);
     235        return (key[0] == cl->in_task_hash);
     236}
     237
     238static void client_remove(link_t *item)
     239{
     240}
     241
     242/** Operations for the client hash table. */
     243static hash_table_operations_t client_hash_table_ops = {
     244        .hash = client_hash,
     245        .compare = client_compare,
     246        .remove_callback = client_remove
     247};
    180248
    181249/** Compute hash into the connection hash table based on the source phone hash.
     
    189257{
    190258        assert(key);
    191         return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS);
     259        return (((*key) >> 4) % CONN_HASH_TABLE_BUCKETS);
    192260}
    193261
     
    480548static int connection_fibril(void *arg)
    481549{
     550        unsigned long key;
     551        client_t *cl;
     552        link_t *lnk;
     553        bool destroy = false;
     554
    482555        /*
    483          * Setup fibril-local connection pointer and call client_connection().
    484          *
     556         * Setup fibril-local connection pointer.
    485557         */
    486558        FIBRIL_connection = (connection_t *) arg;
     559
     560        /*
     561         * Add our reference for the current connection in the client task
     562         * tracking structure. If this is the first reference, create and
     563         * hash in a new tracking structure.
     564         */
     565        futex_down(&async_futex);
     566        key = FIBRIL_connection->in_task_hash;
     567        lnk = hash_table_find(&client_hash_table, &key);
     568        if (lnk) {
     569                cl = hash_table_get_instance(lnk, client_t, link);
     570                cl->refcnt++;
     571        } else {
     572                cl = malloc(sizeof(client_t));
     573                if (!cl) {
     574                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
     575                        futex_up(&async_futex);
     576                        return 0;
     577                }
     578                cl->in_task_hash = FIBRIL_connection->in_task_hash;
     579                async_serialize_start();
     580                cl->data = async_client_data_create();
     581                async_serialize_end();
     582                cl->refcnt = 1;
     583                hash_table_insert(&client_hash_table, &key, &cl->link);
     584        }
     585        futex_up(&async_futex);
     586
     587        FIBRIL_connection->client = cl;
     588
     589        /*
     590         * Call the connection handler function.
     591         */
    487592        FIBRIL_connection->cfibril(FIBRIL_connection->callid,
    488593            &FIBRIL_connection->call);
    489594       
    490         /* Remove myself from the connection hash table */
     595        /*
     596         * Remove the reference for this client task connection.
     597         */
    491598        futex_down(&async_futex);
    492         unsigned long key = FIBRIL_connection->in_phone_hash;
     599        if (--cl->refcnt == 0) {
     600                hash_table_remove(&client_hash_table, &key, 1);
     601                destroy = true;
     602        }
     603        futex_up(&async_futex);
     604
     605        if (destroy) {
     606                if (cl->data)
     607                        async_client_data_destroy(cl->data);
     608                free(cl);
     609        }
     610
     611        /*
     612         * Remove myself from the connection hash table.
     613         */
     614        futex_down(&async_futex);
     615        key = FIBRIL_connection->in_phone_hash;
    493616        hash_table_remove(&conn_hash_table, &key, 1);
    494617        futex_up(&async_futex);
    495618       
    496         /* Answer all remaining messages with EHANGUP */
     619        /*
     620         * Answer all remaining messages with EHANGUP.
     621         */
    497622        while (!list_empty(&FIBRIL_connection->msg_queue)) {
    498623                msg_t *msg;
     
    505630        }
    506631       
     632        /*
     633         * If the connection was hung-up, answer the last call,
     634         * i.e. IPC_M_PHONE_HUNGUP.
     635         */
    507636        if (FIBRIL_connection->close_callid)
    508637                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
     
    517646 * particular fibrils.
    518647 *
     648 * @param in_task_hash  Identification of the incoming connection.
    519649 * @param in_phone_hash Identification of the incoming connection.
    520650 * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
     
    529659 *
    530660 */
    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 *))
     661fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
     662    ipc_callid_t callid, ipc_call_t *call,
     663    void (*cfibril)(ipc_callid_t, ipc_call_t *))
    533664{
    534665        connection_t *conn = malloc(sizeof(*conn));
     
    539670        }
    540671       
     672        conn->in_task_hash = in_task_hash;
    541673        conn->in_phone_hash = in_phone_hash;
    542674        list_initialize(&conn->msg_queue);
     
    592724        case IPC_M_CONNECT_ME_TO:
    593725                /* Open new connection with fibril etc. */
    594                 async_new_connection(IPC_GET_ARG5(*call), callid, call,
    595                     client_connection);
     726                async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
     727                    callid, call, client_connection);
    596728                goto out;
    597729        }
     
    744876int __async_init(void)
    745877{
    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");
     878        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
     879            &client_hash_table_ops) || !hash_table_create(&conn_hash_table,
     880            CONN_HASH_TABLE_BUCKETS, 1, &conn_hash_table_ops)) {
    749881                return ENOMEM;
    750882        }
Note: See TracChangeset for help on using the changeset viewer.