Changes in uspace/lib/c/generic/async/server.c [e768aea:3bd1d7d4] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async/server.c
re768aea r3bd1d7d4 120 120 #include <abi/mm/as.h> 121 121 #include "../private/libc.h" 122 #include "../private/fibril.h"123 122 124 123 /** Async framework global futex */ … … 432 431 * Remove myself from the connection hash table. 433 432 */ 434 futex_ lock(&async_futex);433 futex_down(&async_futex); 435 434 hash_table_remove(&conn_hash_table, &(conn_key_t){ 436 435 .task_id = fibril_connection->in_task_id, 437 436 .phone_hash = fibril_connection->in_phone_hash 438 437 }); 439 futex_u nlock(&async_futex);438 futex_up(&async_futex); 440 439 441 440 /* … … 520 519 /* Add connection to the connection hash table */ 521 520 522 futex_ lock(&async_futex);521 futex_down(&async_futex); 523 522 hash_table_insert(&conn_hash_table, &conn->link); 524 futex_u nlock(&async_futex);523 futex_up(&async_futex); 525 524 526 525 fibril_add_ready(conn->wdata.fid); … … 648 647 assert(call); 649 648 650 futex_ lock(&async_futex);649 futex_down(&async_futex); 651 650 652 651 ht_link_t *link = hash_table_find(&conn_hash_table, &(conn_key_t){ … … 655 654 }); 656 655 if (!link) { 657 futex_u nlock(&async_futex);656 futex_up(&async_futex); 658 657 return false; 659 658 } … … 663 662 msg_t *msg = malloc(sizeof(*msg)); 664 663 if (!msg) { 665 futex_u nlock(&async_futex);664 futex_up(&async_futex); 666 665 return false; 667 666 } … … 687 686 } 688 687 689 futex_u nlock(&async_futex);688 futex_up(&async_futex); 690 689 return true; 691 690 } … … 962 961 connection_t *conn = fibril_connection; 963 962 964 futex_ lock(&async_futex);963 futex_down(&async_futex); 965 964 966 965 if (usecs) { … … 982 981 memset(call, 0, sizeof(ipc_call_t)); 983 982 IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP); 984 futex_u nlock(&async_futex);983 futex_up(&async_futex); 985 984 return conn->close_chandle; 986 985 } … … 997 996 * case, route_call() will perform the wakeup. 998 997 */ 999 fibril_switch(FIBRIL_FROM_BLOCKED); 1000 998 fibril_switch(FIBRIL_TO_MANAGER); 999 1000 /* 1001 * Futex is up after getting back from async_manager. 1002 * Get it again. 1003 */ 1004 futex_down(&async_futex); 1001 1005 if ((usecs) && (conn->wdata.to_event.occurred) && 1002 1006 (list_empty(&conn->msg_queue))) { 1003 1007 /* If we timed out -> exit */ 1004 futex_u nlock(&async_futex);1008 futex_up(&async_futex); 1005 1009 return CAP_NIL; 1006 1010 } … … 1015 1019 free(msg); 1016 1020 1017 futex_u nlock(&async_futex);1021 futex_up(&async_futex); 1018 1022 return chandle; 1019 1023 } … … 1066 1070 assert(call); 1067 1071 1068 if (call->flags & IPC_CALL_ANSWERED) 1069 return; 1070 1071 if (chandle == CAP_NIL) { 1072 if (call->flags & IPC_CALL_NOTIF) { 1073 /* Kernel notification */ 1074 queue_notification(call); 1075 } 1072 /* Kernel notification */ 1073 if ((chandle == CAP_NIL) && (call->flags & IPC_CALL_NOTIF)) { 1074 queue_notification(call); 1076 1075 return; 1077 1076 } … … 1101 1100 1102 1101 /** Fire all timeouts that expired. */ 1103 static suseconds_t handle_expired_timeouts(unsigned int *flags) 1104 { 1105 /* Make sure the async_futex is held. */ 1106 futex_assert_is_locked(&async_futex); 1107 1102 static void handle_expired_timeouts(void) 1103 { 1108 1104 struct timeval tv; 1109 1105 getuptime(&tv); 1110 1106 1111 bool fired = false;1107 futex_down(&async_futex); 1112 1108 1113 1109 link_t *cur = list_first(&timeout_list); … … 1116 1112 list_get_instance(cur, awaiter_t, to_event.link); 1117 1113 1118 if (tv_gt(&waiter->to_event.expires, &tv)) { 1119 if (fired) { 1120 *flags = SYNCH_FLAGS_NON_BLOCKING; 1121 return 0; 1122 } 1123 *flags = 0; 1124 return tv_sub_diff(&waiter->to_event.expires, &tv); 1125 } 1114 if (tv_gt(&waiter->to_event.expires, &tv)) 1115 break; 1126 1116 1127 1117 list_remove(&waiter->to_event.link); … … 1136 1126 waiter->active = true; 1137 1127 fibril_add_ready(waiter->fid); 1138 fired = true;1139 1128 } 1140 1129 … … 1142 1131 } 1143 1132 1144 if (fired) { 1145 *flags = SYNCH_FLAGS_NON_BLOCKING; 1146 return 0; 1147 } 1148 1149 return SYNCH_NO_TIMEOUT; 1133 futex_up(&async_futex); 1150 1134 } 1151 1135 … … 1158 1142 { 1159 1143 while (true) { 1160 futex_lock(&async_futex); 1161 fibril_switch(FIBRIL_FROM_MANAGER); 1162 1163 /* 1164 * The switch only returns when there is no non-manager fibril 1165 * it can run. 1166 */ 1167 1144 if (fibril_switch(FIBRIL_FROM_MANAGER)) { 1145 futex_up(&async_futex); 1146 /* 1147 * async_futex is always held when entering a manager 1148 * fibril. 1149 */ 1150 continue; 1151 } 1152 1153 futex_down(&async_futex); 1154 1155 suseconds_t timeout; 1168 1156 unsigned int flags = SYNCH_FLAGS_NONE; 1169 suseconds_t next_timeout = handle_expired_timeouts(&flags); 1170 futex_unlock(&async_futex); 1157 if (!list_empty(&timeout_list)) { 1158 awaiter_t *waiter = list_get_instance( 1159 list_first(&timeout_list), awaiter_t, to_event.link); 1160 1161 struct timeval tv; 1162 getuptime(&tv); 1163 1164 if (tv_gteq(&tv, &waiter->to_event.expires)) { 1165 futex_up(&async_futex); 1166 handle_expired_timeouts(); 1167 /* 1168 * Notice that even if the event(s) already 1169 * expired (and thus the other fibril was 1170 * supposed to be running already), 1171 * we check for incoming IPC. 1172 * 1173 * Otherwise, a fibril that continuously 1174 * creates (almost) expired events could 1175 * prevent IPC retrieval from the kernel. 1176 */ 1177 timeout = 0; 1178 flags = SYNCH_FLAGS_NON_BLOCKING; 1179 1180 } else { 1181 timeout = tv_sub_diff(&waiter->to_event.expires, 1182 &tv); 1183 futex_up(&async_futex); 1184 } 1185 } else { 1186 futex_up(&async_futex); 1187 timeout = SYNCH_NO_TIMEOUT; 1188 } 1171 1189 1172 1190 atomic_inc(&threads_in_ipc_wait); 1173 1191 1174 1192 ipc_call_t call; 1175 errno_t rc = ipc_wait_cycle(&call, next_timeout, flags);1193 errno_t rc = ipc_wait_cycle(&call, timeout, flags); 1176 1194 1177 1195 atomic_dec(&threads_in_ipc_wait); 1178 1196 1179 1197 assert(rc == EOK); 1198 1199 if (call.cap_handle == CAP_NIL) { 1200 if ((call.flags & 1201 (IPC_CALL_NOTIF | IPC_CALL_ANSWERED)) == 0) { 1202 /* Neither a notification nor an answer. */ 1203 handle_expired_timeouts(); 1204 continue; 1205 } 1206 } 1207 1208 if (call.flags & IPC_CALL_ANSWERED) 1209 continue; 1210 1180 1211 handle_call(call.cap_handle, &call); 1181 1212 } … … 1194 1225 static errno_t async_manager_fibril(void *arg) 1195 1226 { 1227 futex_up(&async_futex); 1228 1229 /* 1230 * async_futex is always locked when entering manager 1231 */ 1196 1232 async_manager_worker(); 1233 1197 1234 return 0; 1198 1235 } … … 1847 1884 } 1848 1885 1849 _Noreturn void async_manager(void)1850 {1851 futex_lock(&async_futex);1852 fibril_switch(FIBRIL_FROM_DEAD);1853 __builtin_unreachable();1854 }1855 1856 1886 /** @} 1857 1887 */
Note:
See TracChangeset
for help on using the changeset viewer.