Rev 2619 | Rev 2635 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2619 | Rev 2621 | ||
|---|---|---|---|
| Line 99... | Line 99... | ||
| 99 | #include <ipc/ipc.h> |
99 | #include <ipc/ipc.h> |
| 100 | #include <assert.h> |
100 | #include <assert.h> |
| 101 | #include <errno.h> |
101 | #include <errno.h> |
| 102 | #include <sys/time.h> |
102 | #include <sys/time.h> |
| 103 | #include <arch/barrier.h> |
103 | #include <arch/barrier.h> |
| - | 104 | #include <bool.h> |
|
| 104 | 105 | ||
| 105 | atomic_t async_futex = FUTEX_INITIALIZER; |
106 | atomic_t async_futex = FUTEX_INITIALIZER; |
| 106 | static hash_table_t conn_hash_table; |
107 | static hash_table_t conn_hash_table; |
| 107 | static LIST_INITIALIZE(timeout_list); |
108 | static LIST_INITIALIZE(timeout_list); |
| 108 | 109 | ||
| Line 173... | Line 174... | ||
| 173 | 174 | ||
| 174 | /** |
175 | /** |
| 175 | * If true, it is forbidden to use async_req functions and all preemption is |
176 | * If true, it is forbidden to use async_req functions and all preemption is |
| 176 | * disabled. |
177 | * disabled. |
| 177 | */ |
178 | */ |
| 178 | __thread int in_interrupt_handler; |
179 | __thread int _in_interrupt_handler; |
| 179 | 180 | ||
| 180 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
181 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
| 181 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
182 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
| 182 | 183 | ||
| 183 | /** |
184 | /** |
| Line 188... | Line 189... | ||
| 188 | * Pointer to a fibril function that will be used to handle interrupt |
189 | * Pointer to a fibril function that will be used to handle interrupt |
| 189 | * notifications. |
190 | * notifications. |
| 190 | */ |
191 | */ |
| 191 | static async_client_conn_t interrupt_received = default_interrupt_received; |
192 | static async_client_conn_t interrupt_received = default_interrupt_received; |
| 192 | 193 | ||
| - | 194 | /* |
|
| - | 195 | * Getter for _in_interrupt_handler. We need to export the value of this thread |
|
| - | 196 | * local variable to other modules, but the binutils 2.18 linkers die on an |
|
| - | 197 | * attempt to export this symbol in the header file. For now, consider this as a |
|
| - | 198 | * workaround. |
|
| - | 199 | */ |
|
| - | 200 | bool in_interrupt_handler(void) |
|
| - | 201 | { |
|
| - | 202 | return _in_interrupt_handler; |
|
| - | 203 | } |
|
| - | 204 | ||
| 193 | #define CONN_HASH_TABLE_CHAINS 32 |
205 | #define CONN_HASH_TABLE_CHAINS 32 |
| 194 | 206 | ||
| 195 | /** Compute hash into the connection hash table based on the source phone hash. |
207 | /** Compute hash into the connection hash table based on the source phone hash. |
| 196 | * |
208 | * |
| 197 | * @param key Pointer to source phone hash. |
209 | * @param key Pointer to source phone hash. |
| Line 515... | Line 527... | ||
| 515 | */ |
527 | */ |
| 516 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
528 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
| 517 | { |
529 | { |
| 518 | /* Unrouted call - do some default behaviour */ |
530 | /* Unrouted call - do some default behaviour */ |
| 519 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
531 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
| 520 | in_interrupt_handler = 1; |
532 | _in_interrupt_handler = 1; |
| 521 | (*interrupt_received)(callid, call); |
533 | (*interrupt_received)(callid, call); |
| 522 | in_interrupt_handler = 0; |
534 | _in_interrupt_handler = 0; |
| 523 | return; |
535 | return; |
| 524 | } |
536 | } |
| 525 | 537 | ||
| 526 | switch (IPC_GET_METHOD(*call)) { |
538 | switch (IPC_GET_METHOD(*call)) { |
| 527 | case IPC_M_CONNECT_ME_TO: |
539 | case IPC_M_CONNECT_ME_TO: |
| Line 714... | Line 726... | ||
| 714 | * |
726 | * |
| 715 | * @param phoneid Handle of the phone that will be used for the send. |
727 | * @param phoneid Handle of the phone that will be used for the send. |
| 716 | * @param method Service-defined method. |
728 | * @param method Service-defined method. |
| 717 | * @param arg1 Service-defined payload argument. |
729 | * @param arg1 Service-defined payload argument. |
| 718 | * @param arg2 Service-defined payload argument. |
730 | * @param arg2 Service-defined payload argument. |
| - | 731 | * @param arg3 Service-defined payload argument. |
|
| - | 732 | * @param arg4 Service-defined payload argument. |
|
| 719 | * @param dataptr If non-NULL, storage where the reply data will be |
733 | * @param dataptr If non-NULL, storage where the reply data will be |
| 720 | * stored. |
734 | * stored. |
| 721 | * |
735 | * |
| 722 | * @return Hash of the sent message. |
736 | * @return Hash of the sent message. |
| 723 | */ |
737 | */ |
| 724 | aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
738 | aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
| 725 | ipc_call_t *dataptr) |
739 | ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) |
| 726 | { |
740 | { |
| 727 | amsg_t *msg; |
741 | amsg_t *msg; |
| 728 | 742 | ||
| 729 | if (in_interrupt_handler) { |
743 | if (_in_interrupt_handler) { |
| 730 | printf("Cannot send asynchronous request in interrupt " |
744 | printf("Cannot send asynchronous request in interrupt " |
| 731 | "handler.\n"); |
745 | "handler.\n"); |
| 732 | _exit(1); |
746 | _exit(1); |
| 733 | } |
747 | } |
| 734 | 748 | ||
| Line 737... | Line 751... | ||
| 737 | msg->dataptr = dataptr; |
751 | msg->dataptr = dataptr; |
| 738 | 752 | ||
| 739 | /* We may sleep in the next method, but it will use its own mechanism */ |
753 | /* We may sleep in the next method, but it will use its own mechanism */ |
| 740 | msg->wdata.active = 1; |
754 | msg->wdata.active = 1; |
| 741 | 755 | ||
| 742 | ipc_call_async_2(phoneid, method, arg1, arg2, msg, reply_received, 1); |
756 | ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
| - | 757 | reply_received, 1); |
|
| 743 | 758 | ||
| 744 | return (aid_t) msg; |
759 | return (aid_t) msg; |
| 745 | } |
760 | } |
| 746 | 761 | ||
| 747 | /** Send message and return id of the sent message |
762 | /** Send message and return id of the sent message |
| Line 752... | Line 767... | ||
| 752 | * @param phoneid Handle of the phone that will be used for the send. |
767 | * @param phoneid Handle of the phone that will be used for the send. |
| 753 | * @param method Service-defined method. |
768 | * @param method Service-defined method. |
| 754 | * @param arg1 Service-defined payload argument. |
769 | * @param arg1 Service-defined payload argument. |
| 755 | * @param arg2 Service-defined payload argument. |
770 | * @param arg2 Service-defined payload argument. |
| 756 | * @param arg3 Service-defined payload argument. |
771 | * @param arg3 Service-defined payload argument. |
| - | 772 | * @param arg4 Service-defined payload argument. |
|
| - | 773 | * @param arg5 Service-defined payload argument. |
|
| 757 | * @param dataptr If non-NULL, storage where the reply data will be |
774 | * @param dataptr If non-NULL, storage where the reply data will be |
| 758 | * stored. |
775 | * stored. |
| 759 | * |
776 | * |
| 760 | * @return Hash of the sent message. |
777 | * @return Hash of the sent message. |
| 761 | */ |
778 | */ |
| 762 | aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
779 | aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
| - | 780 | ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
|
| 763 | ipcarg_t arg3, ipc_call_t *dataptr) |
781 | ipc_call_t *dataptr) |
| 764 | { |
782 | { |
| 765 | amsg_t *msg; |
783 | amsg_t *msg; |
| 766 | 784 | ||
| 767 | if (in_interrupt_handler) { |
785 | if (_in_interrupt_handler) { |
| 768 | printf("Cannot send asynchronous request in interrupt " |
786 | printf("Cannot send asynchronous request in interrupt " |
| 769 | "handler.\n"); |
787 | "handler.\n"); |
| 770 | _exit(1); |
788 | _exit(1); |
| 771 | } |
789 | } |
| 772 | 790 | ||
| Line 774... | Line 792... | ||
| 774 | msg->done = 0; |
792 | msg->done = 0; |
| 775 | msg->dataptr = dataptr; |
793 | msg->dataptr = dataptr; |
| 776 | 794 | ||
| 777 | /* We may sleep in next method, but it will use its own mechanism */ |
795 | /* We may sleep in next method, but it will use its own mechanism */ |
| 778 | msg->wdata.active = 1; |
796 | msg->wdata.active = 1; |
| 779 | 797 | ||
| 780 | ipc_call_async_3(phoneid, method, arg1, arg2, arg3, msg, reply_received, |
798 | ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
| 781 | 1); |
799 | reply_received, 1); |
| 782 | 800 | ||
| 783 | return (aid_t) msg; |
801 | return (aid_t) msg; |
| 784 | } |
802 | } |
| 785 | 803 | ||
| 786 | /** Wait for a message sent by the async framework. |
804 | /** Wait for a message sent by the async framework. |
| Line 864... | Line 882... | ||
| 864 | */ |
882 | */ |
| 865 | void async_usleep(suseconds_t timeout) |
883 | void async_usleep(suseconds_t timeout) |
| 866 | { |
884 | { |
| 867 | amsg_t *msg; |
885 | amsg_t *msg; |
| 868 | 886 | ||
| 869 | if (in_interrupt_handler) { |
887 | if (_in_interrupt_handler) { |
| 870 | printf("Cannot call async_usleep in interrupt handler.\n"); |
888 | printf("Cannot call async_usleep in interrupt handler.\n"); |
| 871 | _exit(1); |
889 | _exit(1); |
| 872 | } |
890 | } |
| 873 | 891 | ||
| 874 | msg = malloc(sizeof(*msg)); |
892 | msg = malloc(sizeof(*msg)); |
| Line 906... | Line 924... | ||
| 906 | void async_set_interrupt_received(async_client_conn_t conn) |
924 | void async_set_interrupt_received(async_client_conn_t conn) |
| 907 | { |
925 | { |
| 908 | interrupt_received = conn; |
926 | interrupt_received = conn; |
| 909 | } |
927 | } |
| 910 | 928 | ||
| 911 | /* Primitive functions for simple communication */ |
929 | /** Pseudo-synchronous message sending - fast version. |
| - | 930 | * |
|
| - | 931 | * Send message asynchronously and return only after the reply arrives. |
|
| - | 932 | * |
|
| - | 933 | * This function can only transfer 4 register payload arguments. For |
|
| - | 934 | * transferring more arguments, see the slower async_req_slow(). |
|
| - | 935 | * |
|
| - | 936 | * @param phoneid Hash of the phone through which to make the call. |
|
| - | 937 | * @param method Method of the call. |
|
| - | 938 | * @param arg1 Service-defined payload argument. |
|
| - | 939 | * @param arg2 Service-defined payload argument. |
|
| - | 940 | * @param arg3 Service-defined payload argument. |
|
| - | 941 | * @param arg4 Service-defined payload argument. |
|
| - | 942 | * @param r1 If non-NULL, storage for the 1st reply argument. |
|
| - | 943 | * @param r2 If non-NULL, storage for the 2nd reply argument. |
|
| - | 944 | * @param r3 If non-NULL, storage for the 3rd reply argument. |
|
| - | 945 | * @param r4 If non-NULL, storage for the 4th reply argument. |
|
| - | 946 | * @param r5 If non-NULL, storage for the 5th reply argument. |
|
| - | 947 | * @return Return code of the reply or a negative error code. |
|
| - | 948 | */ |
|
| 912 | void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1, |
949 | ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
| - | 950 | ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2, |
|
| 913 | ipcarg_t arg2, ipcarg_t arg3) |
951 | ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
| 914 | { |
952 | { |
| - | 953 | ipc_call_t result; |
|
| - | 954 | ipcarg_t rc; |
|
| - | 955 | ||
| 915 | ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, |
956 | aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4, |
| 916 | !in_interrupt_handler); |
957 | &result); |
| - | 958 | async_wait_for(eid, &rc); |
|
| - | 959 | if (r1) |
|
| - | 960 | *r1 = IPC_GET_ARG1(result); |
|
| - | 961 | if (r2) |
|
| - | 962 | *r2 = IPC_GET_ARG2(result); |
|
| - | 963 | if (r3) |
|
| - | 964 | *r3 = IPC_GET_ARG3(result); |
|
| - | 965 | if (r4) |
|
| - | 966 | *r4 = IPC_GET_ARG4(result); |
|
| - | 967 | if (r5) |
|
| - | 968 | *r5 = IPC_GET_ARG5(result); |
|
| - | 969 | return rc; |
|
| 917 | } |
970 | } |
| 918 | 971 | ||
| - | 972 | /** Pseudo-synchronous message sending - slow version. |
|
| - | 973 | * |
|
| - | 974 | * Send message asynchronously and return only after the reply arrives. |
|
| - | 975 | * |
|
| - | 976 | * @param phoneid Hash of the phone through which to make the call. |
|
| - | 977 | * @param method Method of the call. |
|
| - | 978 | * @param arg1 Service-defined payload argument. |
|
| - | 979 | * @param arg2 Service-defined payload argument. |
|
| - | 980 | * @param arg3 Service-defined payload argument. |
|
| - | 981 | * @param arg4 Service-defined payload argument. |
|
| - | 982 | * @param arg5 Service-defined payload argument. |
|
| - | 983 | * @param r1 If non-NULL, storage for the 1st reply argument. |
|
| - | 984 | * @param r2 If non-NULL, storage for the 2nd reply argument. |
|
| - | 985 | * @param r3 If non-NULL, storage for the 3rd reply argument. |
|
| - | 986 | * @param r4 If non-NULL, storage for the 4th reply argument. |
|
| - | 987 | * @param r5 If non-NULL, storage for the 5th reply argument. |
|
| - | 988 | * @return Return code of the reply or a negative error code. |
|
| - | 989 | */ |
|
| 919 | void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2) |
990 | ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
| - | 991 | ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1, |
|
| - | 992 | ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
|
| 920 | { |
993 | { |
| - | 994 | ipc_call_t result; |
|
| - | 995 | ipcarg_t rc; |
|
| - | 996 | ||
| 921 | ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, |
997 | aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, |
| 922 | !in_interrupt_handler); |
998 | &result); |
| - | 999 | async_wait_for(eid, &rc); |
|
| - | 1000 | if (r1) |
|
| - | 1001 | *r1 = IPC_GET_ARG1(result); |
|
| - | 1002 | if (r2) |
|
| - | 1003 | *r2 = IPC_GET_ARG2(result); |
|
| - | 1004 | if (r3) |
|
| - | 1005 | *r3 = IPC_GET_ARG3(result); |
|
| - | 1006 | if (r4) |
|
| - | 1007 | *r4 = IPC_GET_ARG4(result); |
|
| - | 1008 | if (r5) |
|
| - | 1009 | *r5 = IPC_GET_ARG5(result); |
|
| - | 1010 | return rc; |
|
| 923 | } |
1011 | } |
| 924 | 1012 | ||
| 925 | /** @} |
1013 | /** @} |
| 926 | */ |
1014 | */ |
| 927 | 1015 | ||