Subversion Repositories HelenOS-historic

Rev

Rev 1596 | Rev 1614 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1596 Rev 1610
Line 132... Line 132...
132
    ipc_callid_t callid;
132
    ipc_callid_t callid;
133
    ipc_call_t call;
133
    ipc_call_t call;
134
    void (*cthread)(ipc_callid_t,ipc_call_t *);
134
    void (*cthread)(ipc_callid_t,ipc_call_t *);
135
} connection_t;
135
} connection_t;
136
 
136
 
137
 
-
 
-
 
137
/** Identifier of incoming connection handled by current thread */
138
__thread connection_t *PS_connection;
138
__thread connection_t *PS_connection;
-
 
139
/** If true, it is forbidden to use async_req functions and
-
 
140
 *  all preemption is disabled */
-
 
141
__thread int in_interrupt_handler;
139
 
142
 
140
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
143
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
141
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
144
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
142
static async_client_conn_t client_connection = default_client_connection;
145
static async_client_conn_t client_connection = default_client_connection;
143
static async_client_conn_t interrupt_received = default_interrupt_received;
146
static async_client_conn_t interrupt_received = default_interrupt_received;
Line 223... Line 226...
223
{
226
{
224
    link_t *tmp;
227
    link_t *tmp;
225
    awaiter_t *cur;
228
    awaiter_t *cur;
226
 
229
 
227
    wd->timedout = 0;
230
    wd->timedout = 0;
-
 
231
    wd->inlist = 1;
228
 
232
 
229
    tmp = timeout_list.next;
233
    tmp = timeout_list.next;
230
    while (tmp != &timeout_list) {
234
    while (tmp != &timeout_list) {
231
        cur = list_get_instance(tmp, awaiter_t, link);
235
        cur = list_get_instance(tmp, awaiter_t, link);
232
        if (tv_gteq(&cur->expires, &wd->expires))
236
        if (tv_gteq(&cur->expires, &wd->expires))
Line 292... Line 296...
292
     *           I would never expect to find so many errors in
296
     *           I would never expect to find so many errors in
293
     *           compiler *($&$(*&$
297
     *           compiler *($&$(*&$
294
     */
298
     */
295
    conn = PS_connection;
299
    conn = PS_connection;
296
 
300
 
297
    if (usecs < 0) /* TODO: let it get through the ipc_call once */
-
 
298
        return 0;
-
 
299
 
-
 
300
    futex_down(&async_futex);
301
    futex_down(&async_futex);
301
 
302
 
302
    if (usecs) {
303
    if (usecs) {
303
        gettimeofday(&conn->wdata.expires, NULL);
304
        gettimeofday(&conn->wdata.expires, NULL);
304
        tv_add(&conn->wdata.expires, usecs);
305
        tv_add(&conn->wdata.expires, usecs);
305
    } else {
306
    } else {
306
        conn->wdata.inlist = 0;
307
        conn->wdata.inlist = 0;
307
    }
308
    }
308
    /* If nothing in queue, wait until something appears */
309
    /* If nothing in queue, wait until something appears */
309
    while (list_empty(&conn->msg_queue)) {
310
    while (list_empty(&conn->msg_queue)) {
310
        if (usecs) {
311
        if (usecs)
311
            conn->wdata.inlist = 1;
-
 
312
            insert_timeout(&conn->wdata);
312
            insert_timeout(&conn->wdata);
313
        }
313
 
314
        conn->wdata.active = 0;
314
        conn->wdata.active = 0;
315
        psthread_schedule_next_adv(PS_TO_MANAGER);
315
        psthread_schedule_next_adv(PS_TO_MANAGER);
316
        /* Futex is up after getting back from async_manager
316
        /* Futex is up after getting back from async_manager
317
         * get it again */
317
         * get it again */
318
        futex_down(&async_futex);
318
        futex_down(&async_futex);
Line 360... Line 360...
360
    msg_t *msg;
360
    msg_t *msg;
361
 
361
 
362
    /* Setup thread local connection pointer */
362
    /* Setup thread local connection pointer */
363
    PS_connection = (connection_t *)arg;
363
    PS_connection = (connection_t *)arg;
364
    PS_connection->cthread(PS_connection->callid, &PS_connection->call);
364
    PS_connection->cthread(PS_connection->callid, &PS_connection->call);
365
 
-
 
366
    /* Remove myself from connection hash table */
365
    /* Remove myself from connection hash table */
367
    futex_down(&async_futex);
366
    futex_down(&async_futex);
368
    key = PS_connection->in_phone_hash;
367
    key = PS_connection->in_phone_hash;
369
    hash_table_remove(&conn_hash_table, &key, 1);
368
    hash_table_remove(&conn_hash_table, &key, 1);
370
    futex_up(&async_futex);
369
    futex_up(&async_futex);
Line 433... Line 432...
433
static void handle_call(ipc_callid_t callid, ipc_call_t *call)
432
static void handle_call(ipc_callid_t callid, ipc_call_t *call)
434
{
433
{
435
    /* Unrouted call - do some default behaviour */
434
    /* Unrouted call - do some default behaviour */
436
    switch (IPC_GET_METHOD(*call)) {
435
    switch (IPC_GET_METHOD(*call)) {
437
    case IPC_M_INTERRUPT:
436
    case IPC_M_INTERRUPT:
-
 
437
        in_interrupt_handler = 1;
438
        (*interrupt_received)(callid,call);
438
        (*interrupt_received)(callid,call);
-
 
439
        in_interrupt_handler = 0;
439
        return;
440
        return;
440
    case IPC_M_CONNECT_ME_TO:
441
    case IPC_M_CONNECT_ME_TO:
441
        /* Open new connection with thread etc. */
442
        /* Open new connection with thread etc. */
442
        async_new_connection(IPC_GET_ARG3(*call), callid, call, client_connection);
443
        async_new_connection(IPC_GET_ARG3(*call), callid, call, client_connection);
443
        return;
444
        return;
Line 483... Line 484...
483
 
484
 
484
    futex_up(&async_futex);
485
    futex_up(&async_futex);
485
}
486
}
486
 
487
 
487
/** Endless loop dispatching incoming calls and answers */
488
/** Endless loop dispatching incoming calls and answers */
488
int async_manager(void)
489
static int async_manager_worker(void)
489
{
490
{
490
    ipc_call_t call;
491
    ipc_call_t call;
491
    ipc_callid_t callid;
492
    ipc_callid_t callid;
492
    int timeout;
493
    int timeout;
493
    awaiter_t *waiter;
494
    awaiter_t *waiter;
Line 519... Line 520...
519
        if (!callid) {
520
        if (!callid) {
520
            handle_expired_timeouts();
521
            handle_expired_timeouts();
521
            continue;
522
            continue;
522
        }
523
        }
523
 
524
 
524
        if (callid & IPC_CALLID_ANSWERED)
525
        if (callid & IPC_CALLID_ANSWERED) {
525
            continue;
526
            continue;
-
 
527
        }
526
 
528
 
527
        handle_call(callid, &call);
529
        handle_call(callid, &call);
528
    }
530
    }
529
}
531
}
530
 
532
 
Line 535... Line 537...
535
 * currently one async_manager is started automatically per kernel
537
 * currently one async_manager is started automatically per kernel
536
 * thread except main thread.
538
 * thread except main thread.
537
 */
539
 */
538
static int async_manager_thread(void *arg)
540
static int async_manager_thread(void *arg)
539
{
541
{
-
 
542
    in_interrupt_handler = 0; // TODO: Handle TLS better
540
    futex_up(&async_futex); /* async_futex is always locked when entering
543
    futex_up(&async_futex); /* async_futex is always locked when entering
541
                * manager */
544
                * manager */
542
    async_manager();
545
    async_manager_worker();
543
}
546
}
544
 
547
 
545
/** Add one manager to manager list */
548
/** Add one manager to manager list */
546
void async_create_manager(void)
549
void async_create_manager(void)
547
{
550
{
Line 605... Line 608...
605
aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
608
aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
606
           ipc_call_t *dataptr)
609
           ipc_call_t *dataptr)
607
{
610
{
608
    amsg_t *msg;
611
    amsg_t *msg;
609
 
612
 
-
 
613
    if (in_interrupt_handler) {
-
 
614
        printf("Cannot send asynchronou request in interrupt handler.\n");
-
 
615
        _exit(1);
-
 
616
    }
-
 
617
 
610
    msg = malloc(sizeof(*msg));
618
    msg = malloc(sizeof(*msg));
611
    msg->done = 0;
619
    msg->done = 0;
612
    msg->dataptr = dataptr;
620
    msg->dataptr = dataptr;
613
 
621
 
614
    msg->wdata.active = 1; /* We may sleep in next method, but it
622
    msg->wdata.active = 1; /* We may sleep in next method, but it
Line 626... Line 634...
626
aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
634
aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
627
           ipcarg_t arg3, ipc_call_t *dataptr)
635
           ipcarg_t arg3, ipc_call_t *dataptr)
628
{
636
{
629
    amsg_t *msg;
637
    amsg_t *msg;
630
 
638
 
-
 
639
    if (in_interrupt_handler) {
-
 
640
        printf("Cannot send asynchronou request in interrupt handler.\n");
-
 
641
        _exit(1);
-
 
642
    }
-
 
643
 
631
    msg = malloc(sizeof(*msg));
644
    msg = malloc(sizeof(*msg));
632
    msg->done = 0;
645
    msg->done = 0;
633
    msg->dataptr = dataptr;
646
    msg->dataptr = dataptr;
634
 
647
 
635
    msg->wdata.active = 1; /* We may sleep in next method, but it
648
    msg->wdata.active = 1; /* We may sleep in next method, but it
Line 696... Line 709...
696
    gettimeofday(&msg->wdata.expires, NULL);
709
    gettimeofday(&msg->wdata.expires, NULL);
697
    tv_add(&msg->wdata.expires, timeout);
710
    tv_add(&msg->wdata.expires, timeout);
698
 
711
 
699
    msg->wdata.ptid = psthread_get_id();
712
    msg->wdata.ptid = psthread_get_id();
700
    msg->wdata.active = 0;
713
    msg->wdata.active = 0;
701
    msg->wdata.inlist = 1;
-
 
702
 
-
 
703
    insert_timeout(&msg->wdata);
714
    insert_timeout(&msg->wdata);
704
 
715
 
705
    /* Leave locked async_futex when entering this function */
716
    /* Leave locked async_futex when entering this function */
706
    psthread_schedule_next_adv(PS_TO_MANAGER);
717
    psthread_schedule_next_adv(PS_TO_MANAGER);
707
    /* futex is up automatically after psthread_schedule_next...*/
718
    /* futex is up automatically after psthread_schedule_next...*/
Line 723... Line 734...
723
 */
734
 */
724
void async_usleep(suseconds_t timeout)
735
void async_usleep(suseconds_t timeout)
725
{
736
{
726
    amsg_t *msg;
737
    amsg_t *msg;
727
   
738
   
-
 
739
    if (in_interrupt_handler) {
-
 
740
        printf("Cannot call async_usleep in interrupt handler.\n");
-
 
741
        _exit(1);
-
 
742
    }
-
 
743
 
728
    msg = malloc(sizeof(*msg));
744
    msg = malloc(sizeof(*msg));
729
    if (!msg)
745
    if (!msg)
730
        return;
746
        return;
731
 
747
 
732
    msg->wdata.ptid = psthread_get_id();
748
    msg->wdata.ptid = psthread_get_id();
733
    msg->wdata.inlist = 1;
-
 
734
    msg->wdata.active = 0;
749
    msg->wdata.active = 0;
735
 
750
 
736
    gettimeofday(&msg->wdata.expires, NULL);
751
    gettimeofday(&msg->wdata.expires, NULL);
737
    tv_add(&msg->wdata.expires, timeout);
752
    tv_add(&msg->wdata.expires, timeout);
738
 
753
 
Line 754... Line 769...
754
}
769
}
755
void async_set_interrupt_received(async_client_conn_t conn)
770
void async_set_interrupt_received(async_client_conn_t conn)
756
{
771
{
757
    interrupt_received = conn;
772
    interrupt_received = conn;
758
}
773
}
-
 
774
 
-
 
775
/* Primitive functions for simple communication */
-
 
776
void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
-
 
777
         ipcarg_t arg2, ipcarg_t arg3)
-
 
778
{
-
 
779
    ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, !in_interrupt_handler);
-
 
780
}
-
 
781
 
-
 
782
void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)
-
 
783
{
-
 
784
    ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, !in_interrupt_handler);
-
 
785
}