~jsvoboda/helenos/dnsr

« back to all changes in this revision

Viewing changes to uspace/lib/c/generic/async.c

  • Committer: Jiri Svoboda
  • Date: 2012-11-11 21:31:03 UTC
  • mfrom: (1527.1.178 mainline)
  • Revision ID: jiri@wiwaxia-20121111213103-314bmkettwvlwj97
MergeĀ mainlineĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
113
113
#include <mem.h>
114
114
#include <stdlib.h>
115
115
#include <macros.h>
 
116
#include "private/libc.h"
116
117
 
117
 
#define CLIENT_HASH_TABLE_BUCKETS  32
118
 
#define CONN_HASH_TABLE_BUCKETS    32
119
118
 
120
119
/** Session data */
121
120
struct async_sess {
203
202
 
204
203
/* Client connection data */
205
204
typedef struct {
206
 
        link_t link;
 
205
        ht_link_t link;
207
206
        
208
207
        task_id_t in_task_id;
209
208
        atomic_t refcnt;
215
214
        awaiter_t wdata;
216
215
        
217
216
        /** Hash table link. */
218
 
        link_t link;
 
217
        ht_link_t link;
219
218
        
220
219
        /** Incoming client task ID. */
221
220
        task_id_t in_task_id;
391
390
static hash_table_t conn_hash_table;
392
391
static LIST_INITIALIZE(timeout_list);
393
392
 
394
 
static hash_index_t client_hash(unsigned long key[])
395
 
{
396
 
        assert(key);
397
 
        
398
 
        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
399
 
}
400
 
 
401
 
static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
402
 
{
403
 
        assert(key);
404
 
        assert(keys == 2);
405
 
        assert(item);
406
 
        
407
 
        client_t *client = hash_table_get_instance(item, client_t, link);
408
 
        return (key[0] == LOWER32(client->in_task_id) &&
409
 
            (key[1] == UPPER32(client->in_task_id)));
410
 
}
411
 
 
412
 
static void client_remove(link_t *item)
413
 
{
414
 
}
 
393
static size_t client_key_hash(void *k)
 
394
{
 
395
        task_id_t key = *(task_id_t*)k;
 
396
        return key;
 
397
}
 
398
 
 
399
static size_t client_hash(const ht_link_t *item)
 
400
{
 
401
        client_t *client = hash_table_get_inst(item, client_t, link);
 
402
        return client_key_hash(&client->in_task_id);
 
403
}
 
404
 
 
405
static bool client_key_equal(void *k, const ht_link_t *item)
 
406
{
 
407
        task_id_t key = *(task_id_t*)k;
 
408
        client_t *client = hash_table_get_inst(item, client_t, link);
 
409
        return key == client->in_task_id;
 
410
}
 
411
 
415
412
 
416
413
/** Operations for the client hash table. */
417
 
static hash_table_operations_t client_hash_table_ops = {
 
414
static hash_table_ops_t client_hash_table_ops = {
418
415
        .hash = client_hash,
419
 
        .compare = client_compare,
420
 
        .remove_callback = client_remove
 
416
        .key_hash = client_key_hash,
 
417
        .key_equal = client_key_equal,
 
418
        .equal = NULL,
 
419
        .remove_callback = NULL
421
420
};
422
421
 
423
422
/** Compute hash into the connection hash table based on the source phone hash.
427
426
 * @return Index into the connection hash table.
428
427
 *
429
428
 */
430
 
static hash_index_t conn_hash(unsigned long key[])
431
 
{
432
 
        assert(key);
433
 
        
434
 
        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
435
 
}
436
 
 
437
 
/** Compare hash table item with a key.
438
 
 *
439
 
 * @param key  Array containing the source phone hash as the only item.
440
 
 * @param keys Expected 1 but ignored.
441
 
 * @param item Connection hash table item.
442
 
 *
443
 
 * @return True on match, false otherwise.
444
 
 *
445
 
 */
446
 
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
447
 
{
448
 
        assert(key);
449
 
        assert(item);
450
 
        
451
 
        connection_t *conn = hash_table_get_instance(item, connection_t, link);
452
 
        return (key[0] == conn->in_phone_hash);
453
 
}
454
 
 
455
 
static void conn_remove(link_t *item)
456
 
{
457
 
}
 
429
static size_t conn_key_hash(void *key)
 
430
{
 
431
        sysarg_t in_phone_hash  = *(sysarg_t*)key;
 
432
        return in_phone_hash ;
 
433
}
 
434
 
 
435
static size_t conn_hash(const ht_link_t *item)
 
436
{
 
437
        connection_t *conn = hash_table_get_inst(item, connection_t, link);
 
438
        return conn_key_hash(&conn->in_phone_hash);
 
439
}
 
440
 
 
441
static bool conn_key_equal(void *key, const ht_link_t *item)
 
442
{
 
443
        sysarg_t in_phone_hash = *(sysarg_t*)key;
 
444
        connection_t *conn = hash_table_get_inst(item, connection_t, link);
 
445
        return (in_phone_hash == conn->in_phone_hash);
 
446
}
 
447
 
458
448
 
459
449
/** Operations for the connection hash table. */
460
 
static hash_table_operations_t conn_hash_table_ops = {
 
450
static hash_table_ops_t conn_hash_table_ops = {
461
451
        .hash = conn_hash,
462
 
        .compare = conn_compare,
463
 
        .remove_callback = conn_remove
 
452
        .key_hash = conn_key_hash,
 
453
        .key_equal = conn_key_equal,
 
454
        .equal = NULL,
 
455
        .remove_callback = NULL
464
456
};
465
457
 
466
458
/** Sort in current fibril's timeout request.
508
500
        
509
501
        futex_down(&async_futex);
510
502
        
511
 
        unsigned long key = call->in_phone_hash;
512
 
        link_t *hlp = hash_table_find(&conn_hash_table, &key);
 
503
        ht_link_t *hlp = hash_table_find(&conn_hash_table, &call->in_phone_hash);
513
504
        
514
505
        if (!hlp) {
515
506
                futex_up(&async_futex);
516
507
                return false;
517
508
        }
518
509
        
519
 
        connection_t *conn = hash_table_get_instance(hlp, connection_t, link);
 
510
        connection_t *conn = hash_table_get_inst(hlp, connection_t, link);
520
511
        
521
512
        msg_t *msg = malloc(sizeof(*msg));
522
513
        if (!msg) {
636
627
        futex_down(&async_futex);
637
628
        
638
629
        if (usecs) {
639
 
                gettimeofday(&conn->wdata.to_event.expires, NULL);
 
630
                getuptime(&conn->wdata.to_event.expires);
640
631
                tv_add(&conn->wdata.to_event.expires, usecs);
641
632
        } else
642
633
                conn->wdata.to_event.inlist = false;
696
687
 
697
688
static client_t *async_client_get(task_id_t client_id, bool create)
698
689
{
699
 
        unsigned long key[2] = {
700
 
                LOWER32(client_id),
701
 
                UPPER32(client_id),
702
 
        };
703
690
        client_t *client = NULL;
704
691
 
705
692
        futex_down(&async_futex);
706
 
        link_t *lnk = hash_table_find(&client_hash_table, key);
 
693
        ht_link_t *lnk = hash_table_find(&client_hash_table, &client_id);
707
694
        if (lnk) {
708
 
                client = hash_table_get_instance(lnk, client_t, link);
 
695
                client = hash_table_get_inst(lnk, client_t, link);
709
696
                atomic_inc(&client->refcnt);
710
697
        } else if (create) {
711
698
                client = malloc(sizeof(client_t));
714
701
                        client->data = async_client_data_create();
715
702
                
716
703
                        atomic_set(&client->refcnt, 1);
717
 
                        hash_table_insert(&client_hash_table, key, &client->link);
 
704
                        hash_table_insert(&client_hash_table, &client->link);
718
705
                }
719
706
        }
720
707
 
725
712
static void async_client_put(client_t *client)
726
713
{
727
714
        bool destroy;
728
 
        unsigned long key[2] = {
729
 
                LOWER32(client->in_task_id),
730
 
                UPPER32(client->in_task_id)
731
 
        };
732
 
        
 
715
 
733
716
        futex_down(&async_futex);
734
717
        
735
718
        if (atomic_predec(&client->refcnt) == 0) {
736
 
                hash_table_remove(&client_hash_table, key, 2);
 
719
                hash_table_remove(&client_hash_table, &client->in_task_id);
737
720
                destroy = true;
738
721
        } else
739
722
                destroy = false;
829
812
         * Remove myself from the connection hash table.
830
813
         */
831
814
        futex_down(&async_futex);
832
 
        unsigned long key = fibril_connection->in_phone_hash;
833
 
        hash_table_remove(&conn_hash_table, &key, 1);
 
815
        hash_table_remove(&conn_hash_table, &fibril_connection->in_phone_hash);
834
816
        futex_up(&async_futex);
835
817
        
836
818
        /*
914
896
        }
915
897
        
916
898
        /* Add connection to the connection hash table */
917
 
        unsigned long key = conn->in_phone_hash;
918
899
        
919
900
        futex_down(&async_futex);
920
 
        hash_table_insert(&conn_hash_table, &key, &conn->link);
 
901
        hash_table_insert(&conn_hash_table, &conn->link);
921
902
        futex_up(&async_futex);
922
903
        
923
904
        fibril_add_ready(conn->wdata.fid);
965
946
static void handle_expired_timeouts(void)
966
947
{
967
948
        struct timeval tv;
968
 
        gettimeofday(&tv, NULL);
 
949
        getuptime(&tv);
969
950
        
970
951
        futex_down(&async_futex);
971
952
        
1022
1003
                            list_first(&timeout_list), awaiter_t, to_event.link);
1023
1004
                        
1024
1005
                        struct timeval tv;
1025
 
                        gettimeofday(&tv, NULL);
 
1006
                        getuptime(&tv);
1026
1007
                        
1027
1008
                        if (tv_gteq(&tv, &waiter->to_event.expires)) {
1028
1009
                                futex_up(&async_futex);
1109
1090
 */
1110
1091
void __async_init(void)
1111
1092
{
1112
 
        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
1113
 
            2, &client_hash_table_ops))
 
1093
        if (!hash_table_create(&client_hash_table, 0, 0, &client_hash_table_ops))
1114
1094
                abort();
1115
1095
        
1116
 
        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
1117
 
            1, &conn_hash_table_ops))
 
1096
        if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops))
1118
1097
                abort();
1119
1098
        
1120
1099
        session_ns = (async_sess_t *) malloc(sizeof(async_sess_t));
1329
1308
        if (timeout < 0)
1330
1309
                timeout = 0;
1331
1310
 
1332
 
        gettimeofday(&msg->wdata.to_event.expires, NULL);
 
1311
        getuptime(&msg->wdata.to_event.expires);
1333
1312
        tv_add(&msg->wdata.to_event.expires, timeout);
1334
1313
        
1335
1314
        /*
1411
1390
        
1412
1391
        msg->wdata.fid = fibril_get_id();
1413
1392
        
1414
 
        gettimeofday(&msg->wdata.to_event.expires, NULL);
 
1393
        getuptime(&msg->wdata.to_event.expires);
1415
1394
        tv_add(&msg->wdata.to_event.expires, timeout);
1416
1395
        
1417
1396
        futex_down(&async_futex);
2165
2144
 */
2166
2145
int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
2167
2146
{
2168
 
        return ipc_share_in_finalize(callid, src, flags);
 
2147
        return ipc_answer_3(callid, EOK, (sysarg_t) src, (sysarg_t) flags,
 
2148
            (sysarg_t) __entry);
2169
2149
}
2170
2150
 
2171
2151
/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
2232
2212
 */
2233
2213
int async_share_out_finalize(ipc_callid_t callid, void **dst)
2234
2214
{
2235
 
        return ipc_share_out_finalize(callid, dst);
 
2215
        return ipc_answer_2(callid, EOK, (sysarg_t) __entry, (sysarg_t) dst);
2236
2216
}
2237
2217
 
2238
2218
/** Start IPC_M_DATA_READ using the async framework.
2316
2296
 */
2317
2297
int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
2318
2298
{
2319
 
        return ipc_data_read_finalize(callid, src, size);
 
2299
        return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) size);
2320
2300
}
2321
2301
 
2322
2302
/** Wrapper for forwarding any read request
2419
2399
 */
2420
2400
int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
2421
2401
{
2422
 
        return ipc_data_write_finalize(callid, dst, size);
 
2402
        return ipc_answer_2(callid, EOK, (sysarg_t) dst, (sysarg_t) size);
2423
2403
}
2424
2404
 
2425
2405
/** Wrapper for receiving binary data or strings