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 |