Rev 4407 | Rev 4509 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4407 | Rev 4475 | ||
---|---|---|---|
Line 176... | Line 176... | ||
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 | __thread 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 | static void default_pending(void); |
|
181 | 182 | ||
182 | /** |
183 | /** |
183 | * Pointer to a fibril function that will be used to handle connections. |
184 | * Pointer to a fibril function that will be used to handle connections. |
184 | */ |
185 | */ |
185 | static async_client_conn_t client_connection = default_client_connection; |
186 | static async_client_conn_t client_connection = default_client_connection; |
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 | * Pointer to a fibril function that will be used to handle pending |
|
- | 196 | * operations. |
|
- | 197 | */ |
|
- | 198 | static async_pending_t pending = default_pending; |
|
193 | 199 | ||
194 | static hash_table_t conn_hash_table; |
200 | static hash_table_t conn_hash_table; |
195 | static LIST_INITIALIZE(timeout_list); |
201 | static LIST_INITIALIZE(timeout_list); |
196 | 202 | ||
197 | - | ||
198 | #define CONN_HASH_TABLE_CHAINS 32 |
203 | #define CONN_HASH_TABLE_CHAINS 32 |
199 | 204 | ||
200 | /** Compute hash into the connection hash table based on the source phone hash. |
205 | /** Compute hash into the connection hash table based on the source phone hash. |
201 | * |
206 | * |
202 | * @param key Pointer to source phone hash. |
207 | * @param key Pointer to source phone hash. |
Line 374... | Line 379... | ||
374 | 379 | ||
375 | futex_up(&async_futex); |
380 | futex_up(&async_futex); |
376 | return true; |
381 | return true; |
377 | } |
382 | } |
378 | 383 | ||
- | 384 | /** Pending fibril. |
|
- | 385 | * |
|
- | 386 | * After each call the pending operations are executed in a separate |
|
- | 387 | * fibril. The function pending() is c. |
|
- | 388 | * |
|
- | 389 | * @param arg Unused. |
|
- | 390 | * |
|
- | 391 | * @return Always zero. |
|
- | 392 | * |
|
- | 393 | */ |
|
- | 394 | static int pending_fibril(void *arg) |
|
- | 395 | { |
|
- | 396 | pending(); |
|
- | 397 | ||
- | 398 | return 0; |
|
- | 399 | } |
|
- | 400 | ||
- | 401 | /** Process pending actions. |
|
- | 402 | * |
|
- | 403 | * A new fibril is created which would process the pending operations. |
|
- | 404 | * |
|
- | 405 | * @return False if an error occured. |
|
- | 406 | * True if the execution was passed to the pending fibril. |
|
- | 407 | * |
|
- | 408 | */ |
|
- | 409 | static bool process_pending(void) |
|
- | 410 | { |
|
- | 411 | futex_down(&async_futex); |
|
- | 412 | ||
- | 413 | fid_t fid = fibril_create(pending_fibril, NULL); |
|
- | 414 | fibril_add_ready(fid); |
|
- | 415 | ||
- | 416 | futex_up(&async_futex); |
|
- | 417 | return true; |
|
- | 418 | } |
|
- | 419 | ||
379 | /** Return new incoming message for the current (fibril-local) connection. |
420 | /** Return new incoming message for the current (fibril-local) connection. |
380 | * |
421 | * |
381 | * @param call Storage where the incoming call data will be stored. |
422 | * @param call Storage where the incoming call data will be stored. |
382 | * @param usecs Timeout in microseconds. Zero denotes no timeout. |
423 | * @param usecs Timeout in microseconds. Zero denotes no timeout. |
383 | * |
424 | * |
Line 470... | Line 511... | ||
470 | */ |
511 | */ |
471 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
512 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
472 | { |
513 | { |
473 | } |
514 | } |
474 | 515 | ||
- | 516 | /** Default fibril function that gets called to handle pending operations. |
|
- | 517 | * |
|
- | 518 | * This function is defined as a weak symbol - to be redefined in user code. |
|
- | 519 | * |
|
- | 520 | */ |
|
- | 521 | static void default_pending(void) |
|
- | 522 | { |
|
- | 523 | } |
|
- | 524 | ||
475 | /** Wrapper for client connection fibril. |
525 | /** Wrapper for client connection fibril. |
476 | * |
526 | * |
477 | * When a new connection arrives, a fibril with this implementing function is |
527 | * When a new connection arrives, a fibril with this implementing function is |
478 | * created. It calls client_connection() and does the final cleanup. |
528 | * created. It calls client_connection() and does the final cleanup. |
479 | * |
529 | * |
Line 561... | Line 611... | ||
561 | ipc_answer_0(callid, ENOMEM); |
611 | ipc_answer_0(callid, ENOMEM); |
562 | return NULL; |
612 | return NULL; |
563 | } |
613 | } |
564 | 614 | ||
565 | /* Add connection to the connection hash table */ |
615 | /* Add connection to the connection hash table */ |
566 | ipcarg_t key = conn->in_phone_hash; |
616 | unsigned long key = conn->in_phone_hash; |
567 | 617 | ||
568 | futex_down(&async_futex); |
618 | futex_down(&async_futex); |
569 | hash_table_insert(&conn_hash_table, &key, &conn->link); |
619 | hash_table_insert(&conn_hash_table, &key, &conn->link); |
570 | futex_up(&async_futex); |
620 | futex_up(&async_futex); |
571 | 621 | ||
Line 586... | Line 636... | ||
586 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
636 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
587 | { |
637 | { |
588 | /* Unrouted call - do some default behaviour */ |
638 | /* Unrouted call - do some default behaviour */ |
589 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
639 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
590 | process_notification(callid, call); |
640 | process_notification(callid, call); |
591 | return; |
641 | goto out; |
592 | } |
642 | } |
593 | 643 | ||
594 | switch (IPC_GET_METHOD(*call)) { |
644 | switch (IPC_GET_METHOD(*call)) { |
595 | case IPC_M_CONNECT_ME: |
645 | case IPC_M_CONNECT_ME: |
596 | case IPC_M_CONNECT_ME_TO: |
646 | case IPC_M_CONNECT_ME_TO: |
597 | /* Open new connection with fibril etc. */ |
647 | /* Open new connection with fibril etc. */ |
598 | async_new_connection(IPC_GET_ARG5(*call), callid, call, |
648 | async_new_connection(IPC_GET_ARG5(*call), callid, call, |
599 | client_connection); |
649 | client_connection); |
600 | return; |
650 | goto out; |
601 | } |
651 | } |
602 | 652 | ||
603 | /* Try to route the call through the connection hash table */ |
653 | /* Try to route the call through the connection hash table */ |
604 | if (route_call(callid, call)) |
654 | if (route_call(callid, call)) |
605 | return; |
655 | goto out; |
606 | 656 | ||
607 | /* Unknown call from unknown phone - hang it up */ |
657 | /* Unknown call from unknown phone - hang it up */ |
608 | ipc_answer_0(callid, EHANGUP); |
658 | ipc_answer_0(callid, EHANGUP); |
- | 659 | return; |
|
- | 660 | ||
- | 661 | out: |
|
- | 662 | process_pending(); |
|
609 | } |
663 | } |
610 | 664 | ||
611 | /** Fire all timeouts that expired. */ |
665 | /** Fire all timeouts that expired. */ |
612 | static void handle_expired_timeouts(void) |
666 | static void handle_expired_timeouts(void) |
613 | { |
667 | { |
Line 757... | Line 811... | ||
757 | * @param retval Value returned in the answer. |
811 | * @param retval Value returned in the answer. |
758 | * @param data Call data of the answer. |
812 | * @param data Call data of the answer. |
759 | */ |
813 | */ |
760 | static void reply_received(void *arg, int retval, ipc_call_t *data) |
814 | static void reply_received(void *arg, int retval, ipc_call_t *data) |
761 | { |
815 | { |
- | 816 | futex_down(&async_futex); |
|
- | 817 | ||
762 | amsg_t *msg = (amsg_t *) arg; |
818 | amsg_t *msg = (amsg_t *) arg; |
763 | msg->retval = retval; |
819 | msg->retval = retval; |
764 | 820 | ||
765 | futex_down(&async_futex); |
- | |
766 | - | ||
767 | /* Copy data after futex_down, just in case the call was detached */ |
821 | /* Copy data after futex_down, just in case the call was detached */ |
768 | if (msg->dataptr) |
822 | if ((msg->dataptr) && (data)) |
769 | *msg->dataptr = *data; |
823 | *msg->dataptr = *data; |
770 | 824 | ||
771 | write_barrier(); |
825 | write_barrier(); |
772 | 826 | ||
773 | /* Remove message from timeout list */ |
827 | /* Remove message from timeout list */ |
Line 992... | Line 1046... | ||
992 | void async_set_interrupt_received(async_client_conn_t intr) |
1046 | void async_set_interrupt_received(async_client_conn_t intr) |
993 | { |
1047 | { |
994 | interrupt_received = intr; |
1048 | interrupt_received = intr; |
995 | } |
1049 | } |
996 | 1050 | ||
- | 1051 | /** Setter for pending function pointer. |
|
- | 1052 | * |
|
- | 1053 | * @param pend Function that will implement a new pending |
|
- | 1054 | * operations fibril. |
|
- | 1055 | */ |
|
- | 1056 | void async_set_pending(async_pending_t pend) |
|
- | 1057 | { |
|
- | 1058 | pending = pend; |
|
- | 1059 | } |
|
- | 1060 | ||
997 | /** Pseudo-synchronous message sending - fast version. |
1061 | /** Pseudo-synchronous message sending - fast version. |
998 | * |
1062 | * |
999 | * Send message asynchronously and return only after the reply arrives. |
1063 | * Send message asynchronously and return only after the reply arrives. |
1000 | * |
1064 | * |
1001 | * This function can only transfer 4 register payload arguments. For |
1065 | * This function can only transfer 4 register payload arguments. For |