Rev 4377 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4377 | Rev 4692 | ||
---|---|---|---|
Line 93... | Line 93... | ||
93 | 93 | ||
94 | #include <futex.h> |
94 | #include <futex.h> |
95 | #include <async.h> |
95 | #include <async.h> |
96 | #include <fibril.h> |
96 | #include <fibril.h> |
97 | #include <stdio.h> |
97 | #include <stdio.h> |
98 | #include <libadt/hash_table.h> |
98 | #include <adt/hash_table.h> |
99 | #include <libadt/list.h> |
99 | #include <adt/list.h> |
100 | #include <ipc/ipc.h> |
100 | #include <ipc/ipc.h> |
101 | #include <assert.h> |
101 | #include <assert.h> |
102 | #include <errno.h> |
102 | #include <errno.h> |
103 | #include <sys/time.h> |
103 | #include <sys/time.h> |
104 | #include <arch/barrier.h> |
104 | #include <arch/barrier.h> |
Line 172... | Line 172... | ||
172 | /** Fibril function that will be used to handle the connection. */ |
172 | /** Fibril function that will be used to handle the connection. */ |
173 | void (*cfibril)(ipc_callid_t, ipc_call_t *); |
173 | void (*cfibril)(ipc_callid_t, ipc_call_t *); |
174 | } connection_t; |
174 | } connection_t; |
175 | 175 | ||
176 | /** Identifier of the incoming connection handled by the current fibril. */ |
176 | /** Identifier of the incoming connection handled by the current fibril. */ |
177 | __thread connection_t *FIBRIL_connection; |
177 | fibril_local connection_t *FIBRIL_connection; |
178 | 178 | ||
179 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
179 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
180 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
180 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
181 | 181 | ||
182 | /** |
182 | /** |
Line 188... | Line 188... | ||
188 | * Pointer to a fibril function that will be used to handle interrupt |
188 | * Pointer to a fibril function that will be used to handle interrupt |
189 | * notifications. |
189 | * notifications. |
190 | */ |
190 | */ |
191 | static async_client_conn_t interrupt_received = default_interrupt_received; |
191 | static async_client_conn_t interrupt_received = default_interrupt_received; |
192 | 192 | ||
193 | - | ||
194 | static hash_table_t conn_hash_table; |
193 | static hash_table_t conn_hash_table; |
195 | static LIST_INITIALIZE(timeout_list); |
194 | static LIST_INITIALIZE(timeout_list); |
196 | 195 | ||
197 | - | ||
198 | #define CONN_HASH_TABLE_CHAINS 32 |
196 | #define CONN_HASH_TABLE_CHAINS 32 |
199 | 197 | ||
200 | /** Compute hash into the connection hash table based on the source phone hash. |
198 | /** Compute hash into the connection hash table based on the source phone hash. |
201 | * |
199 | * |
202 | * @param key Pointer to source phone hash. |
200 | * @param key Pointer to source phone hash. |
Line 498... | Line 496... | ||
498 | hash_table_remove(&conn_hash_table, &key, 1); |
496 | hash_table_remove(&conn_hash_table, &key, 1); |
499 | futex_up(&async_futex); |
497 | futex_up(&async_futex); |
500 | 498 | ||
501 | /* Answer all remaining messages with EHANGUP */ |
499 | /* Answer all remaining messages with EHANGUP */ |
502 | while (!list_empty(&FIBRIL_connection->msg_queue)) { |
500 | while (!list_empty(&FIBRIL_connection->msg_queue)) { |
503 | msg_t *msg |
501 | msg_t *msg; |
504 | = list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link); |
- | |
505 | 502 | ||
- | 503 | msg = list_get_instance(FIBRIL_connection->msg_queue.next, |
|
- | 504 | msg_t, link); |
|
506 | list_remove(&msg->link); |
505 | list_remove(&msg->link); |
507 | ipc_answer_0(msg->callid, EHANGUP); |
506 | ipc_answer_0(msg->callid, EHANGUP); |
508 | free(msg); |
507 | free(msg); |
509 | } |
508 | } |
510 | 509 | ||
Line 561... | Line 560... | ||
561 | ipc_answer_0(callid, ENOMEM); |
560 | ipc_answer_0(callid, ENOMEM); |
562 | return NULL; |
561 | return NULL; |
563 | } |
562 | } |
564 | 563 | ||
565 | /* Add connection to the connection hash table */ |
564 | /* Add connection to the connection hash table */ |
566 | ipcarg_t key = conn->in_phone_hash; |
565 | unsigned long key = conn->in_phone_hash; |
567 | 566 | ||
568 | futex_down(&async_futex); |
567 | futex_down(&async_futex); |
569 | hash_table_insert(&conn_hash_table, &key, &conn->link); |
568 | hash_table_insert(&conn_hash_table, &key, &conn->link); |
570 | futex_up(&async_futex); |
569 | futex_up(&async_futex); |
571 | 570 | ||
Line 586... | Line 585... | ||
586 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
585 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
587 | { |
586 | { |
588 | /* Unrouted call - do some default behaviour */ |
587 | /* Unrouted call - do some default behaviour */ |
589 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
588 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
590 | process_notification(callid, call); |
589 | process_notification(callid, call); |
591 | return; |
590 | goto out; |
592 | } |
591 | } |
593 | 592 | ||
594 | switch (IPC_GET_METHOD(*call)) { |
593 | switch (IPC_GET_METHOD(*call)) { |
- | 594 | case IPC_M_CONNECT_ME: |
|
595 | case IPC_M_CONNECT_ME_TO: |
595 | case IPC_M_CONNECT_ME_TO: |
596 | /* Open new connection with fibril etc. */ |
596 | /* Open new connection with fibril etc. */ |
597 | async_new_connection(IPC_GET_ARG5(*call), callid, call, |
597 | async_new_connection(IPC_GET_ARG5(*call), callid, call, |
598 | client_connection); |
598 | client_connection); |
599 | return; |
599 | goto out; |
600 | } |
600 | } |
601 | 601 | ||
602 | /* Try to route the call through the connection hash table */ |
602 | /* Try to route the call through the connection hash table */ |
603 | if (route_call(callid, call)) |
603 | if (route_call(callid, call)) |
604 | return; |
604 | goto out; |
605 | 605 | ||
606 | /* Unknown call from unknown phone - hang it up */ |
606 | /* Unknown call from unknown phone - hang it up */ |
607 | ipc_answer_0(callid, EHANGUP); |
607 | ipc_answer_0(callid, EHANGUP); |
- | 608 | return; |
|
- | 609 | ||
- | 610 | out: |
|
- | 611 | ; |
|
608 | } |
612 | } |
609 | 613 | ||
610 | /** Fire all timeouts that expired. */ |
614 | /** Fire all timeouts that expired. */ |
611 | static void handle_expired_timeouts(void) |
615 | static void handle_expired_timeouts(void) |
612 | { |
616 | { |
Line 660... | Line 664... | ||
660 | 664 | ||
661 | futex_down(&async_futex); |
665 | futex_down(&async_futex); |
662 | 666 | ||
663 | suseconds_t timeout; |
667 | suseconds_t timeout; |
664 | if (!list_empty(&timeout_list)) { |
668 | if (!list_empty(&timeout_list)) { |
665 | awaiter_t *waiter |
669 | awaiter_t *waiter = list_get_instance(timeout_list.next, |
666 | = list_get_instance(timeout_list.next, awaiter_t, link); |
670 | awaiter_t, link); |
667 | 671 | ||
668 | struct timeval tv; |
672 | struct timeval tv; |
669 | gettimeofday(&tv, NULL); |
673 | gettimeofday(&tv, NULL); |
670 | 674 | ||
671 | if (tv_gteq(&tv, &waiter->expires)) { |
675 | if (tv_gteq(&tv, &waiter->expires)) { |
Line 678... | Line 682... | ||
678 | timeout = SYNCH_NO_TIMEOUT; |
682 | timeout = SYNCH_NO_TIMEOUT; |
679 | 683 | ||
680 | futex_up(&async_futex); |
684 | futex_up(&async_futex); |
681 | 685 | ||
682 | ipc_call_t call; |
686 | ipc_call_t call; |
683 | ipc_callid_t callid |
687 | ipc_callid_t callid = ipc_wait_cycle(&call, timeout, |
684 | = ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE); |
688 | SYNCH_FLAGS_NONE); |
685 | 689 | ||
686 | if (!callid) { |
690 | if (!callid) { |
687 | handle_expired_timeouts(); |
691 | handle_expired_timeouts(); |
688 | continue; |
692 | continue; |
689 | } |
693 | } |
Line 732... | Line 736... | ||
732 | 736 | ||
733 | /** Initialize the async framework. |
737 | /** Initialize the async framework. |
734 | * |
738 | * |
735 | * @return Zero on success or an error code. |
739 | * @return Zero on success or an error code. |
736 | */ |
740 | */ |
737 | int _async_init(void) |
741 | int __async_init(void) |
738 | { |
742 | { |
739 | if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, |
743 | if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, |
740 | &conn_hash_table_ops)) { |
744 | &conn_hash_table_ops)) { |
741 | printf("%s: cannot create hash table\n", "async"); |
745 | printf("%s: cannot create hash table\n", "async"); |
742 | return ENOMEM; |
746 | return ENOMEM; |
Line 756... | Line 760... | ||
756 | * @param retval Value returned in the answer. |
760 | * @param retval Value returned in the answer. |
757 | * @param data Call data of the answer. |
761 | * @param data Call data of the answer. |
758 | */ |
762 | */ |
759 | static void reply_received(void *arg, int retval, ipc_call_t *data) |
763 | static void reply_received(void *arg, int retval, ipc_call_t *data) |
760 | { |
764 | { |
- | 765 | futex_down(&async_futex); |
|
- | 766 | ||
761 | amsg_t *msg = (amsg_t *) arg; |
767 | amsg_t *msg = (amsg_t *) arg; |
762 | msg->retval = retval; |
768 | msg->retval = retval; |
763 | 769 | ||
764 | futex_down(&async_futex); |
- | |
765 | - | ||
766 | /* Copy data after futex_down, just in case the call was detached */ |
770 | /* Copy data after futex_down, just in case the call was detached */ |
767 | if (msg->dataptr) |
771 | if ((msg->dataptr) && (data)) |
768 | *msg->dataptr = *data; |
772 | *msg->dataptr = *data; |
769 | 773 | ||
770 | write_barrier(); |
774 | write_barrier(); |
771 | 775 | ||
772 | /* Remove message from timeout list */ |
776 | /* Remove message from timeout list */ |
Line 808... | Line 812... | ||
808 | return 0; |
812 | return 0; |
809 | 813 | ||
810 | msg->done = false; |
814 | msg->done = false; |
811 | msg->dataptr = dataptr; |
815 | msg->dataptr = dataptr; |
812 | 816 | ||
- | 817 | msg->wdata.inlist = false; |
|
813 | /* We may sleep in the next method, but it will use its own mechanism */ |
818 | /* We may sleep in the next method, but it will use its own mechanism */ |
814 | msg->wdata.active = true; |
819 | msg->wdata.active = true; |
815 | 820 | ||
816 | ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
821 | ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
817 | reply_received, true); |
822 | reply_received, true); |
Line 847... | Line 852... | ||
847 | return 0; |
852 | return 0; |
848 | 853 | ||
849 | msg->done = false; |
854 | msg->done = false; |
850 | msg->dataptr = dataptr; |
855 | msg->dataptr = dataptr; |
851 | 856 | ||
- | 857 | msg->wdata.inlist = false; |
|
852 | /* We may sleep in next method, but it will use its own mechanism */ |
858 | /* We may sleep in next method, but it will use its own mechanism */ |
853 | msg->wdata.active = true; |
859 | msg->wdata.active = true; |
854 | 860 | ||
855 | ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
861 | ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
856 | reply_received, true); |
862 | reply_received, true); |