Changeset c80fdd0 in mainline


Ignore:
Timestamp:
2011-01-25T21:28:26Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
46eec3b
Parents:
f21a61e
Message:

Track and reference count connections from the same client task.

File:
1 edited

Legend:

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

    rf21a61e rc80fdd0  
    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       
     
    176183static async_client_conn_t interrupt_received = default_interrupt_received;
    177184
     185static hash_table_t client_hash_table;
    178186static hash_table_t conn_hash_table;
    179187static LIST_INITIALIZE(timeout_list);
    180188
    181 #define CONN_HASH_TABLE_CHAINS  32
     189#define CLIENT_HASH_TABLE_BUCKETS       32
     190#define CONN_HASH_TABLE_BUCKETS         32
     191
     192static hash_index_t client_hash(unsigned long *key)
     193{
     194        assert(key);
     195        return (((*key) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
     196}
     197
     198static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
     199{
     200        client_t *cl = hash_table_get_instance(item, client_t, link);
     201        return (key[0] == cl->in_task_hash);
     202}
     203
     204static void client_remove(link_t *item)
     205{
     206}
     207
     208/** Operations for the client hash table. */
     209static hash_table_operations_t client_hash_table_ops = {
     210        .hash = client_hash,
     211        .compare = client_compare,
     212        .remove_callback = client_remove
     213};
    182214
    183215/** Compute hash into the connection hash table based on the source phone hash.
     
    191223{
    192224        assert(key);
    193         return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS);
     225        return (((*key) >> 4) % CONN_HASH_TABLE_BUCKETS);
    194226}
    195227
     
    482514static int connection_fibril(void *arg)
    483515{
     516        unsigned long key;
     517        client_t *cl;
     518        link_t *lnk;
     519
    484520        /*
    485          * Setup fibril-local connection pointer and call client_connection().
    486          *
     521         * Setup fibril-local connection pointer.
    487522         */
    488523        FIBRIL_connection = (connection_t *) arg;
     524
     525        /*
     526         * Add our reference for the current connection in the client task
     527         * tracking structure. If this is the first reference, create and
     528         * hash in a new tracking structure.
     529         */
     530        futex_down(&async_futex);
     531        key = FIBRIL_connection->in_task_hash;
     532        lnk = hash_table_find(&client_hash_table, &key);
     533        if (lnk) {
     534                cl = hash_table_get_instance(lnk, client_t, link);
     535                cl->refcnt++;
     536        } else {
     537                cl = malloc(sizeof(client_t));
     538                if (!cl) {
     539                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
     540                        futex_up(&async_futex);
     541                        return 0;
     542                }
     543                cl->in_task_hash = FIBRIL_connection->in_task_hash;
     544                cl->data = NULL;
     545                cl->refcnt = 1;
     546                hash_table_insert(&client_hash_table, &key, &cl->link);
     547        }
     548        futex_up(&async_futex);
     549
     550        /*
     551         * Call the connection handler function.
     552         */
    489553        FIBRIL_connection->cfibril(FIBRIL_connection->callid,
    490554            &FIBRIL_connection->call);
    491555       
    492         /* Remove myself from the connection hash table */
     556        /*
     557         * Remove the reference for this client task connection.
     558         */
    493559        futex_down(&async_futex);
    494         unsigned long key = FIBRIL_connection->in_phone_hash;
     560        if (--cl->refcnt == 0) {
     561                hash_table_remove(&client_hash_table, &key, 1);
     562                free(cl);
     563        }
     564        futex_up(&async_futex);
     565
     566        /*
     567         * Remove myself from the connection hash table.
     568         */
     569        futex_down(&async_futex);
     570        key = FIBRIL_connection->in_phone_hash;
    495571        hash_table_remove(&conn_hash_table, &key, 1);
    496572        futex_up(&async_futex);
    497573       
    498         /* Answer all remaining messages with EHANGUP */
     574        /*
     575         * Answer all remaining messages with EHANGUP.
     576         */
    499577        while (!list_empty(&FIBRIL_connection->msg_queue)) {
    500578                msg_t *msg;
     
    507585        }
    508586       
     587        /*
     588         * If the connection was hung-up, answer the last call,
     589         * i.e. IPC_M_PHONE_HUNGUP.
     590         */
    509591        if (FIBRIL_connection->close_callid)
    510592                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
     
    749831int __async_init(void)
    750832{
    751         if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1,
    752             &conn_hash_table_ops)) {
    753                 printf("%s: Cannot create async hash table\n", "libc");
     833        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
     834            &client_hash_table_ops) || !hash_table_create(&conn_hash_table,
     835            CONN_HASH_TABLE_BUCKETS, 1, &conn_hash_table_ops)) {
    754836                return ENOMEM;
    755837        }
Note: See TracChangeset for help on using the changeset viewer.