Changes in uspace/lib/c/generic/async/server.c [3bd1d7d4:e768aea] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async/server.c
r3bd1d7d4 re768aea 120 120 #include <abi/mm/as.h> 121 121 #include "../private/libc.h" 122 #include "../private/fibril.h" 122 123 123 124 /** Async framework global futex */ … … 431 432 * Remove myself from the connection hash table. 432 433 */ 433 futex_ down(&async_futex);434 futex_lock(&async_futex); 434 435 hash_table_remove(&conn_hash_table, &(conn_key_t){ 435 436 .task_id = fibril_connection->in_task_id, 436 437 .phone_hash = fibril_connection->in_phone_hash 437 438 }); 438 futex_u p(&async_futex);439 futex_unlock(&async_futex); 439 440 440 441 /* … … 519 520 /* Add connection to the connection hash table */ 520 521 521 futex_ down(&async_futex);522 futex_lock(&async_futex); 522 523 hash_table_insert(&conn_hash_table, &conn->link); 523 futex_u p(&async_futex);524 futex_unlock(&async_futex); 524 525 525 526 fibril_add_ready(conn->wdata.fid); … … 647 648 assert(call); 648 649 649 futex_ down(&async_futex);650 futex_lock(&async_futex); 650 651 651 652 ht_link_t *link = hash_table_find(&conn_hash_table, &(conn_key_t){ … … 654 655 }); 655 656 if (!link) { 656 futex_u p(&async_futex);657 futex_unlock(&async_futex); 657 658 return false; 658 659 } … … 662 663 msg_t *msg = malloc(sizeof(*msg)); 663 664 if (!msg) { 664 futex_u p(&async_futex);665 futex_unlock(&async_futex); 665 666 return false; 666 667 } … … 686 687 } 687 688 688 futex_u p(&async_futex);689 futex_unlock(&async_futex); 689 690 return true; 690 691 } … … 961 962 connection_t *conn = fibril_connection; 962 963 963 futex_ down(&async_futex);964 futex_lock(&async_futex); 964 965 965 966 if (usecs) { … … 981 982 memset(call, 0, sizeof(ipc_call_t)); 982 983 IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP); 983 futex_u p(&async_futex);984 futex_unlock(&async_futex); 984 985 return conn->close_chandle; 985 986 } … … 996 997 * case, route_call() will perform the wakeup. 997 998 */ 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); 999 fibril_switch(FIBRIL_FROM_BLOCKED); 1000 1005 1001 if ((usecs) && (conn->wdata.to_event.occurred) && 1006 1002 (list_empty(&conn->msg_queue))) { 1007 1003 /* If we timed out -> exit */ 1008 futex_u p(&async_futex);1004 futex_unlock(&async_futex); 1009 1005 return CAP_NIL; 1010 1006 } … … 1019 1015 free(msg); 1020 1016 1021 futex_u p(&async_futex);1017 futex_unlock(&async_futex); 1022 1018 return chandle; 1023 1019 } … … 1070 1066 assert(call); 1071 1067 1072 /* Kernel notification */ 1073 if ((chandle == CAP_NIL) && (call->flags & IPC_CALL_NOTIF)) { 1074 queue_notification(call); 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 } 1075 1076 return; 1076 1077 } … … 1100 1101 1101 1102 /** Fire all timeouts that expired. */ 1102 static void handle_expired_timeouts(void) 1103 { 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 1104 1108 struct timeval tv; 1105 1109 getuptime(&tv); 1106 1110 1107 futex_down(&async_futex);1111 bool fired = false; 1108 1112 1109 1113 link_t *cur = list_first(&timeout_list); … … 1112 1116 list_get_instance(cur, awaiter_t, to_event.link); 1113 1117 1114 if (tv_gt(&waiter->to_event.expires, &tv)) 1115 break; 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 } 1116 1126 1117 1127 list_remove(&waiter->to_event.link); … … 1126 1136 waiter->active = true; 1127 1137 fibril_add_ready(waiter->fid); 1138 fired = true; 1128 1139 } 1129 1140 … … 1131 1142 } 1132 1143 1133 futex_up(&async_futex); 1144 if (fired) { 1145 *flags = SYNCH_FLAGS_NON_BLOCKING; 1146 return 0; 1147 } 1148 1149 return SYNCH_NO_TIMEOUT; 1134 1150 } 1135 1151 … … 1142 1158 { 1143 1159 while (true) { 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; 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 1156 1168 unsigned int flags = SYNCH_FLAGS_NONE; 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 } 1169 suseconds_t next_timeout = handle_expired_timeouts(&flags); 1170 futex_unlock(&async_futex); 1189 1171 1190 1172 atomic_inc(&threads_in_ipc_wait); 1191 1173 1192 1174 ipc_call_t call; 1193 errno_t rc = ipc_wait_cycle(&call, timeout, flags);1175 errno_t rc = ipc_wait_cycle(&call, next_timeout, flags); 1194 1176 1195 1177 atomic_dec(&threads_in_ipc_wait); 1196 1178 1197 1179 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 1211 1180 handle_call(call.cap_handle, &call); 1212 1181 } … … 1225 1194 static errno_t async_manager_fibril(void *arg) 1226 1195 { 1227 futex_up(&async_futex);1228 1229 /*1230 * async_futex is always locked when entering manager1231 */1232 1196 async_manager_worker(); 1233 1234 1197 return 0; 1235 1198 } … … 1884 1847 } 1885 1848 1849 _Noreturn void async_manager(void) 1850 { 1851 futex_lock(&async_futex); 1852 fibril_switch(FIBRIL_FROM_DEAD); 1853 __builtin_unreachable(); 1854 } 1855 1886 1856 /** @} 1887 1857 */
Note:
See TracChangeset
for help on using the changeset viewer.