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 | } |