Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async/server.c

    re768aea r3bd1d7d4  
    120120#include <abi/mm/as.h>
    121121#include "../private/libc.h"
    122 #include "../private/fibril.h"
    123122
    124123/** Async framework global futex */
     
    432431         * Remove myself from the connection hash table.
    433432         */
    434         futex_lock(&async_futex);
     433        futex_down(&async_futex);
    435434        hash_table_remove(&conn_hash_table, &(conn_key_t){
    436435                .task_id = fibril_connection->in_task_id,
    437436                .phone_hash = fibril_connection->in_phone_hash
    438437        });
    439         futex_unlock(&async_futex);
     438        futex_up(&async_futex);
    440439
    441440        /*
     
    520519        /* Add connection to the connection hash table */
    521520
    522         futex_lock(&async_futex);
     521        futex_down(&async_futex);
    523522        hash_table_insert(&conn_hash_table, &conn->link);
    524         futex_unlock(&async_futex);
     523        futex_up(&async_futex);
    525524
    526525        fibril_add_ready(conn->wdata.fid);
     
    648647        assert(call);
    649648
    650         futex_lock(&async_futex);
     649        futex_down(&async_futex);
    651650
    652651        ht_link_t *link = hash_table_find(&conn_hash_table, &(conn_key_t){
     
    655654        });
    656655        if (!link) {
    657                 futex_unlock(&async_futex);
     656                futex_up(&async_futex);
    658657                return false;
    659658        }
     
    663662        msg_t *msg = malloc(sizeof(*msg));
    664663        if (!msg) {
    665                 futex_unlock(&async_futex);
     664                futex_up(&async_futex);
    666665                return false;
    667666        }
     
    687686        }
    688687
    689         futex_unlock(&async_futex);
     688        futex_up(&async_futex);
    690689        return true;
    691690}
     
    962961        connection_t *conn = fibril_connection;
    963962
    964         futex_lock(&async_futex);
     963        futex_down(&async_futex);
    965964
    966965        if (usecs) {
     
    982981                        memset(call, 0, sizeof(ipc_call_t));
    983982                        IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP);
    984                         futex_unlock(&async_futex);
     983                        futex_up(&async_futex);
    985984                        return conn->close_chandle;
    986985                }
     
    997996                 * case, route_call() will perform the wakeup.
    998997                 */
    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);
    10011005                if ((usecs) && (conn->wdata.to_event.occurred) &&
    10021006                    (list_empty(&conn->msg_queue))) {
    10031007                        /* If we timed out -> exit */
    1004                         futex_unlock(&async_futex);
     1008                        futex_up(&async_futex);
    10051009                        return CAP_NIL;
    10061010                }
     
    10151019        free(msg);
    10161020
    1017         futex_unlock(&async_futex);
     1021        futex_up(&async_futex);
    10181022        return chandle;
    10191023}
     
    10661070        assert(call);
    10671071
    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);
    10761075                return;
    10771076        }
     
    11011100
    11021101/** 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 
     1102static void handle_expired_timeouts(void)
     1103{
    11081104        struct timeval tv;
    11091105        getuptime(&tv);
    11101106
    1111         bool fired = false;
     1107        futex_down(&async_futex);
    11121108
    11131109        link_t *cur = list_first(&timeout_list);
     
    11161112                    list_get_instance(cur, awaiter_t, to_event.link);
    11171113
    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;
    11261116
    11271117                list_remove(&waiter->to_event.link);
     
    11361126                        waiter->active = true;
    11371127                        fibril_add_ready(waiter->fid);
    1138                         fired = true;
    11391128                }
    11401129
     
    11421131        }
    11431132
    1144         if (fired) {
    1145                 *flags = SYNCH_FLAGS_NON_BLOCKING;
    1146                 return 0;
    1147         }
    1148 
    1149         return SYNCH_NO_TIMEOUT;
     1133        futex_up(&async_futex);
    11501134}
    11511135
     
    11581142{
    11591143        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;
    11681156                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                }
    11711189
    11721190                atomic_inc(&threads_in_ipc_wait);
    11731191
    11741192                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);
    11761194
    11771195                atomic_dec(&threads_in_ipc_wait);
    11781196
    11791197                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
    11801211                handle_call(call.cap_handle, &call);
    11811212        }
     
    11941225static errno_t async_manager_fibril(void *arg)
    11951226{
     1227        futex_up(&async_futex);
     1228
     1229        /*
     1230         * async_futex is always locked when entering manager
     1231         */
    11961232        async_manager_worker();
     1233
    11971234        return 0;
    11981235}
     
    18471884}
    18481885
    1849 _Noreturn void async_manager(void)
    1850 {
    1851         futex_lock(&async_futex);
    1852         fibril_switch(FIBRIL_FROM_DEAD);
    1853         __builtin_unreachable();
    1854 }
    1855 
    18561886/** @}
    18571887 */
Note: See TracChangeset for help on using the changeset viewer.