Changeset 1de92fb0 in mainline
- Timestamp:
- 2018-08-01T18:15:53Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f787c8e
- Parents:
- 6340b4d2
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-31 22:01:34)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-08-01 18:15:53)
- Location:
- uspace/lib/c
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
r6340b4d2 r1de92fb0 143 143 generic/thread/futex.c \ 144 144 generic/thread/rcu.c \ 145 generic/thread/mpsc.c \ 145 146 generic/sysinfo.c \ 146 147 generic/ipc.c \ -
uspace/lib/c/generic/async/server.c
r6340b4d2 r1de92fb0 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 132 126 /* Client connection data */ 133 127 typedef struct { … … 156 150 client_t *client; 157 151 158 /** Message event. */ 159 fibril_event_t msg_arrived; 160 161 /** Messages that should be delivered to this fibril. */ 162 list_t msg_queue; 152 /** Channel for messages that should be delivered to this fibril. */ 153 mpsc_t *msg_channel; 163 154 164 155 /** Call data of the opening call. */ 165 156 ipc_call_t call; 166 167 /** Identification of the closing call. */168 cap_call_handle_t close_chandle;169 157 170 158 /** Fibril function that will be used to handle the connection. */ … … 423 411 async_client_put(client); 424 412 413 fibril_rmutex_lock(&conn_mutex); 414 425 415 /* 426 416 * Remove myself from the connection hash table. 427 417 */ 428 fibril_rmutex_lock(&conn_mutex);429 418 hash_table_remove(&conn_hash_table, &(conn_key_t){ 430 419 .task_id = fibril_connection->in_task_id, 431 420 .phone_hash = fibril_connection->in_phone_hash 432 421 }); 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 433 429 fibril_rmutex_unlock(&conn_mutex); 434 430 … … 436 432 * Answer all remaining messages with EHANGUP. 437 433 */ 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 } 434 ipc_call_t call; 435 while (mpsc_receive(c, &call, NULL) == EOK) 436 ipc_answer_0(call.cap_handle, EHANGUP); 447 437 448 438 /* 449 * If the connection was hung-up, answer the last call, 450 * i.e. IPC_M_PHONE_HUNGUP. 439 * Clean up memory. 451 440 */ 452 if (fibril_connection->close_chandle) 453 ipc_answer_0(fibril_connection->close_chandle, EOK); 454 441 mpsc_destroy(c); 455 442 free(fibril_connection); 456 443 return EOK; … … 488 475 conn->in_task_id = in_task_id; 489 476 conn->in_phone_hash = in_phone_hash; 490 conn->msg_arrived = FIBRIL_EVENT_INIT; 491 list_initialize(&conn->msg_queue); 492 conn->close_chandle = CAP_NIL; 477 conn->msg_channel = mpsc_create(sizeof(ipc_call_t)); 493 478 conn->handler = handler; 494 479 conn->data = data; … … 503 488 504 489 if (conn->fid == 0) { 490 mpsc_destroy(conn->msg_channel); 505 491 free(conn); 506 492 … … 606 592 * @param call Data of the incoming call. 607 593 * 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) 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) 613 600 { 614 601 assert(call); … … 622 609 if (!link) { 623 610 fibril_rmutex_unlock(&conn_mutex); 624 return false;611 return ENOENT; 625 612 } 626 613 627 614 connection_t *conn = hash_table_get_inst(link, connection_t, link); 628 615 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; 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 } 641 626 642 627 fibril_rmutex_unlock(&conn_mutex); 643 644 /* If the connection fibril is waiting for an event, activate it */ 645 fibril_notify(&conn->msg_arrived); 646 return true; 628 return rc; 647 629 } 648 630 … … 939 921 assert(fibril_connection); 940 922 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 in946 * a compiler.947 */948 connection_t *conn = fibril_connection;949 950 923 struct timeval tv; 951 924 struct timeval *expires = NULL; … … 956 929 } 957 930 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); 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 994 946 return true; 995 947 } … … 1071 1023 1072 1024 /* Try to route the call through the connection hash table */ 1073 if (route_call(call)) 1025 errno_t rc = route_call(call); 1026 if (rc == EOK) 1074 1027 return; 1075 1028 1076 /* Unknown call from unknown phone - hang it up */ 1077 ipc_answer_0(call->cap_handle, EHANGUP); 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); 1078 1034 } 1079 1035 -
uspace/lib/c/generic/thread/atomic.c
r6340b4d2 r1de92fb0 36 36 */ 37 37 38 void __sync_synchronize(void) 39 { 40 // FIXME: Full memory barrier. We need a syscall for this. 41 // Should we implement this or is empty definition ok here? 42 } 43 38 44 unsigned __sync_add_and_fetch_4(volatile void *vptr, unsigned val) 39 45 { -
uspace/lib/c/generic/thread/fibril.c
r6340b4d2 r1de92fb0 723 723 } 724 724 725 /** 726 * Wake up the fibril waiting for the given event. 727 * Up to one wakeup is remembered if the fibril is not currently waiting. 728 * 729 * This function is safe for use under restricted mutex lock. 730 */ 725 731 void fibril_notify(fibril_event_t *event) 726 732 { -
uspace/lib/c/include/fibril_synch.h
r6340b4d2 r1de92fb0 50 50 * - may not use any other synchronization primitive, 51 51 * save for another `fibril_rmutex_t`. This includes nonblocking 52 * operations like cvar signal and mutex unlock. 52 * operations like cvar signal and mutex unlock, unless otherwise 53 * specified. 53 54 * - may not read IPC messages 54 55 * - may not start a new thread/fibril … … 245 246 extern void fibril_semaphore_close(fibril_semaphore_t *); 246 247 248 typedef struct mpsc mpsc_t; 249 extern mpsc_t *mpsc_create(size_t); 250 extern void mpsc_destroy(mpsc_t *); 251 extern errno_t mpsc_send(mpsc_t *, const void *); 252 extern errno_t mpsc_receive(mpsc_t *, void *, const struct timeval *); 253 extern void mpsc_close(mpsc_t *); 254 247 255 #endif 248 256
Note:
See TracChangeset
for help on using the changeset viewer.