Subversion Repositories HelenOS

Rev

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