Changes in uspace/lib/c/generic/async/server.c [1de92fb0:8080262] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async/server.c
r1de92fb0 r8080262 124 124 #define DPRINTF(...) ((void) 0) 125 125 126 /** Call data */ 127 typedef struct { 128 link_t link; 129 ipc_call_t call; 130 } msg_t; 131 126 132 /* Client connection data */ 127 133 typedef struct { … … 150 156 client_t *client; 151 157 152 /** Channel for messages that should be delivered to this fibril. */ 153 mpsc_t *msg_channel; 158 /** Message event. */ 159 fibril_event_t msg_arrived; 160 161 /** Messages that should be delivered to this fibril. */ 162 list_t msg_queue; 154 163 155 164 /** Call data of the opening call. */ 156 165 ipc_call_t call; 166 167 /** Identification of the closing call. */ 168 cap_call_handle_t close_chandle; 157 169 158 170 /** Fibril function that will be used to handle the connection. */ … … 411 423 async_client_put(client); 412 424 413 fibril_rmutex_lock(&conn_mutex);414 415 425 /* 416 426 * Remove myself from the connection hash table. 417 427 */ 428 fibril_rmutex_lock(&conn_mutex); 418 429 hash_table_remove(&conn_hash_table, &(conn_key_t){ 419 430 .task_id = fibril_connection->in_task_id, 420 431 .phone_hash = fibril_connection->in_phone_hash 421 432 }); 422 423 /*424 * Close the channel, if it isn't closed already.425 */426 mpsc_t *c = fibril_connection->msg_channel;427 mpsc_close(c);428 429 433 fibril_rmutex_unlock(&conn_mutex); 430 434 … … 432 436 * Answer all remaining messages with EHANGUP. 433 437 */ 434 ipc_call_t call; 435 while (mpsc_receive(c, &call, NULL) == EOK) 436 ipc_answer_0(call.cap_handle, EHANGUP); 438 while (!list_empty(&fibril_connection->msg_queue)) { 439 msg_t *msg = 440 list_get_instance(list_first(&fibril_connection->msg_queue), 441 msg_t, link); 442 443 list_remove(&msg->link); 444 ipc_answer_0(msg->call.cap_handle, EHANGUP); 445 free(msg); 446 } 437 447 438 448 /* 439 * Clean up memory. 449 * If the connection was hung-up, answer the last call, 450 * i.e. IPC_M_PHONE_HUNGUP. 440 451 */ 441 mpsc_destroy(c); 452 if (fibril_connection->close_chandle) 453 ipc_answer_0(fibril_connection->close_chandle, EOK); 454 442 455 free(fibril_connection); 443 456 return EOK; … … 475 488 conn->in_task_id = in_task_id; 476 489 conn->in_phone_hash = in_phone_hash; 477 conn->msg_channel = mpsc_create(sizeof(ipc_call_t)); 490 conn->msg_arrived = FIBRIL_EVENT_INIT; 491 list_initialize(&conn->msg_queue); 492 conn->close_chandle = CAP_NIL; 478 493 conn->handler = handler; 479 494 conn->data = data; … … 488 503 489 504 if (conn->fid == 0) { 490 mpsc_destroy(conn->msg_channel);491 505 free(conn); 492 506 … … 592 606 * @param call Data of the incoming call. 593 607 * 594 * @return EOK if the call was successfully passed to the respective fibril. 595 * @return ENOENT if the call doesn't match any connection. 596 * @return Other error code if routing failed for other reasons. 597 * 598 */ 599 static errno_t route_call(ipc_call_t *call) 608 * @return False if the call doesn't match any connection. 609 * @return True if the call was passed to the respective connection fibril. 610 * 611 */ 612 static bool route_call(ipc_call_t *call) 600 613 { 601 614 assert(call); … … 609 622 if (!link) { 610 623 fibril_rmutex_unlock(&conn_mutex); 611 return ENOENT;624 return false; 612 625 } 613 626 614 627 connection_t *conn = hash_table_get_inst(link, connection_t, link); 615 628 616 errno_t rc = mpsc_send(conn->msg_channel, call); 617 618 if (IPC_GET_IMETHOD(*call) == IPC_M_PHONE_HUNGUP) { 619 /* Close the channel, but let the connection fibril answer. */ 620 mpsc_close(conn->msg_channel); 621 // FIXME: Ideally, we should be able to discard/answer the 622 // hungup message here and just close the channel without 623 // passing it out. Unfortunatelly, somehow that breaks 624 // handling of CPU exceptions. 625 } 629 // FIXME: malloc in critical section 630 msg_t *msg = malloc(sizeof(*msg)); 631 if (!msg) { 632 fibril_rmutex_unlock(&conn_mutex); 633 return false; 634 } 635 636 msg->call = *call; 637 list_append(&msg->link, &conn->msg_queue); 638 639 if (IPC_GET_IMETHOD(*call) == IPC_M_PHONE_HUNGUP) 640 conn->close_chandle = call->cap_handle; 626 641 627 642 fibril_rmutex_unlock(&conn_mutex); 628 return rc; 643 644 /* If the connection fibril is waiting for an event, activate it */ 645 fibril_notify(&conn->msg_arrived); 646 return true; 629 647 } 630 648 … … 921 939 assert(fibril_connection); 922 940 941 /* 942 * Why doing this? 943 * GCC 4.1.0 coughs on fibril_connection-> dereference. 944 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. 945 * I would never expect to find so many errors in 946 * a compiler. 947 */ 948 connection_t *conn = fibril_connection; 949 923 950 struct timeval tv; 924 951 struct timeval *expires = NULL; … … 929 956 } 930 957 931 errno_t rc = mpsc_receive(fibril_connection->msg_channel, 932 call, expires); 933 934 if (rc == ETIMEOUT) 935 return false; 936 937 if (rc != EOK) { 938 /* 939 * The async_get_call_timeout() interface doesn't support 940 * propagating errors. Return a null call instead. 941 */ 942 943 memset(call, 0, sizeof(ipc_call_t)); 944 } 945 958 fibril_rmutex_lock(&conn_mutex); 959 960 /* If nothing in queue, wait until something arrives */ 961 while (list_empty(&conn->msg_queue)) { 962 if (conn->close_chandle) { 963 /* 964 * Handle the case when the connection was already 965 * closed by the client but the server did not notice 966 * the first IPC_M_PHONE_HUNGUP call and continues to 967 * call async_get_call_timeout(). Repeat 968 * IPC_M_PHONE_HUNGUP until the caller notices. 969 */ 970 memset(call, 0, sizeof(ipc_call_t)); 971 IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP); 972 fibril_rmutex_unlock(&conn_mutex); 973 return true; 974 } 975 976 // TODO: replace with cvar 977 fibril_rmutex_unlock(&conn_mutex); 978 979 errno_t rc = fibril_wait_timeout(&conn->msg_arrived, expires); 980 if (rc == ETIMEOUT) 981 return false; 982 983 fibril_rmutex_lock(&conn_mutex); 984 } 985 986 msg_t *msg = list_get_instance(list_first(&conn->msg_queue), 987 msg_t, link); 988 list_remove(&msg->link); 989 990 *call = msg->call; 991 free(msg); 992 993 fibril_rmutex_unlock(&conn_mutex); 946 994 return true; 947 995 } … … 1023 1071 1024 1072 /* Try to route the call through the connection hash table */ 1025 errno_t rc = route_call(call); 1026 if (rc == EOK) 1073 if (route_call(call)) 1027 1074 return; 1028 1075 1029 // TODO: Log the error. 1030 1031 if (call->cap_handle != CAP_NIL) 1032 /* Unknown call from unknown phone - hang it up */ 1033 ipc_answer_0(call->cap_handle, EHANGUP); 1076 /* Unknown call from unknown phone - hang it up */ 1077 ipc_answer_0(call->cap_handle, EHANGUP); 1034 1078 } 1035 1079
Note:
See TracChangeset
for help on using the changeset viewer.