Changeset ab6edb6 in mainline


Ignore:
Timestamp:
2018-06-26T17:34:48Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e768aea
Parents:
b59318e
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-25 19:28:19)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:34:48)
Message:

Simplify the interaction between async_futex and fibril_switch().

Location:
uspace/lib/c/generic
Files:
6 edited

Legend:

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

    rb59318e rab6edb6  
    372372
    373373        /* Leave the async_futex locked when entering this function */
    374         fibril_switch(FIBRIL_TO_MANAGER);
    375 
    376         /* Futex is up automatically after fibril_switch */
     374        fibril_switch(FIBRIL_FROM_BLOCKED);
     375        futex_unlock(&async_futex);
    377376
    378377done:
     
    445444
    446445        /* Leave the async_futex locked when entering this function */
    447         fibril_switch(FIBRIL_TO_MANAGER);
    448 
    449         /* Futex is up automatically after fibril_switch */
     446        fibril_switch(FIBRIL_FROM_BLOCKED);
     447        futex_unlock(&async_futex);
    450448
    451449        if (!msg->done)
     
    511509
    512510        /* Leave the async_futex locked when entering this function */
    513         fibril_switch(FIBRIL_TO_MANAGER);
    514 
    515         /* Futex is up automatically after fibril_switch() */
     511        fibril_switch(FIBRIL_FROM_BLOCKED);
     512        futex_unlock(&async_futex);
    516513}
    517514
  • uspace/lib/c/generic/async/server.c

    rb59318e rab6edb6  
    997997                 * case, route_call() will perform the wakeup.
    998998                 */
    999                 fibril_switch(FIBRIL_TO_MANAGER);
    1000 
    1001                 /*
    1002                  * Futex is up after getting back from async_manager.
    1003                  * Get it again.
    1004                  */
    1005                 futex_lock(&async_futex);
     999                fibril_switch(FIBRIL_FROM_BLOCKED);
     1000
    10061001                if ((usecs) && (conn->wdata.to_event.occurred) &&
    10071002                    (list_empty(&conn->msg_queue))) {
     
    11431138{
    11441139        while (true) {
    1145                 if (fibril_switch(FIBRIL_FROM_MANAGER)) {
    1146                         futex_unlock(&async_futex);
    1147                         /*
    1148                          * async_futex is always held when entering a manager
    1149                          * fibril.
    1150                          */
    1151                         continue;
    1152                 }
    1153 
    11541140                futex_lock(&async_futex);
     1141                fibril_switch(FIBRIL_FROM_MANAGER);
     1142
     1143                /*
     1144                 * The switch only returns when there is no non-manager fibril
     1145                 * it can run.
     1146                 */
    11551147
    11561148                suseconds_t timeout;
     
    12261218static errno_t async_manager_fibril(void *arg)
    12271219{
    1228         futex_unlock(&async_futex);
    1229 
    1230         /*
    1231          * async_futex is always locked when entering manager
    1232          */
    12331220        async_manager_worker();
    1234 
    12351221        return 0;
    12361222}
  • uspace/lib/c/generic/fibril.c

    rb59318e rab6edb6  
    7171static void fibril_main(void)
    7272{
    73         /* fibril_futex is locked when a fibril is first started. */
    74         futex_unlock(&fibril_futex);
     73        /* fibril_futex and async_futex are locked when a fibril is started. */
     74        futex_unlock(&fibril_futex);
     75        futex_unlock(&async_futex);
    7576
    7677        fibril_t *fibril = fibril_self();
     
    127128/** Switch from the current fibril.
    128129 *
    129  * If stype is FIBRIL_TO_MANAGER or FIBRIL_FROM_DEAD, the async_futex must
    130  * be held.
     130 * The async_futex must be held when entering this function,
     131 * and is still held on return.
    131132 *
    132133 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
     
    140141int fibril_switch(fibril_switch_type_t stype)
    141142{
     143        /* Make sure the async_futex is held. */
     144        futex_assert_is_locked(&async_futex);
     145
    142146        futex_lock(&fibril_futex);
    143147
     
    146150
    147151        /* Choose a new fibril to run */
    148         switch (stype) {
    149         case FIBRIL_TO_MANAGER:
    150         case FIBRIL_FROM_DEAD:
    151                 /* Make sure the async_futex is held. */
    152                 futex_assert_is_locked(&async_futex);
     152        if (list_empty(&ready_list)) {
     153                if (stype == FIBRIL_PREEMPT) {
     154                        // FIXME: This means that as long as there is a fibril
     155                        // that only yields, IPC messages are never retrieved.
     156                        futex_unlock(&fibril_futex);
     157                        return 0;
     158                }
    153159
    154160                /* If we are going to manager and none exists, create it */
     
    161167                dstf = list_get_instance(list_first(&manager_list),
    162168                    fibril_t, link);
    163 
    164                 /* Bookkeeping. */
    165                 futex_give_to(&async_futex, dstf);
    166 
    167                 if (stype == FIBRIL_FROM_DEAD)
    168                         dstf->clean_after_me = srcf;
    169                 break;
    170         case FIBRIL_PREEMPT:
    171         case FIBRIL_FROM_MANAGER:
    172                 futex_assert_is_not_locked(&async_futex);
    173 
    174                 if (list_empty(&ready_list)) {
    175                         futex_unlock(&fibril_futex);
    176                         return 0;
    177                 }
    178 
     169        } else {
    179170                dstf = list_get_instance(list_first(&ready_list), fibril_t,
    180171                    link);
    181                 break;
    182         }
     172        }
     173
    183174        list_remove(&dstf->link);
     175        if (stype == FIBRIL_FROM_DEAD)
     176                dstf->clean_after_me = srcf;
    184177
    185178        /* Put the current fibril into the correct run list */
     
    192185                break;
    193186        case FIBRIL_FROM_DEAD:
     187        case FIBRIL_FROM_BLOCKED:
    194188                // Nothing.
    195189                break;
    196         case FIBRIL_TO_MANAGER:
    197                 /*
    198                  * Don't put the current fibril into any list, it should
    199                  * already be somewhere, or it will be lost.
    200                  */
    201                 break;
    202190        }
    203191
    204192        /* Bookkeeping. */
    205193        futex_give_to(&fibril_futex, dstf);
     194        futex_give_to(&async_futex, dstf);
    206195
    207196        /* Swap to the next fibril. */
     
    350339void fibril_yield(void)
    351340{
    352         fibril_switch(FIBRIL_PREEMPT);
     341        futex_lock(&async_futex);
     342        (void) fibril_switch(FIBRIL_PREEMPT);
     343        futex_unlock(&async_futex);
    353344}
    354345
  • uspace/lib/c/generic/fibril_synch.c

    rb59318e rab6edb6  
    116116                check_for_deadlock(&fm->oi);
    117117                f->waits_for = &fm->oi;
    118                 fibril_switch(FIBRIL_TO_MANAGER);
     118                fibril_switch(FIBRIL_FROM_BLOCKED);
    119119        } else {
    120120                fm->oi.owned_by = f;
    121                 futex_unlock(&async_futex);
    122         }
     121        }
     122        futex_unlock(&async_futex);
    123123}
    124124
     
    206206                check_for_deadlock(&frw->oi);
    207207                f->waits_for = &frw->oi;
    208                 fibril_switch(FIBRIL_TO_MANAGER);
     208                fibril_switch(FIBRIL_FROM_BLOCKED);
    209209        } else {
    210210                /* Consider the first reader the owner. */
    211211                if (frw->readers++ == 0)
    212212                        frw->oi.owned_by = f;
    213                 futex_unlock(&async_futex);
    214         }
     213        }
     214        futex_unlock(&async_futex);
    215215}
    216216
     
    230230                check_for_deadlock(&frw->oi);
    231231                f->waits_for = &frw->oi;
    232                 fibril_switch(FIBRIL_TO_MANAGER);
     232                fibril_switch(FIBRIL_FROM_BLOCKED);
    233233        } else {
    234234                frw->oi.owned_by = f;
    235235                frw->writers++;
    236                 futex_unlock(&async_futex);
    237         }
     236        }
     237        futex_unlock(&async_futex);
    238238}
    239239
     
    377377        list_append(&wdata.wu_event.link, &fcv->waiters);
    378378        _fibril_mutex_unlock_unsafe(fm);
    379         fibril_switch(FIBRIL_TO_MANAGER);
     379        fibril_switch(FIBRIL_FROM_BLOCKED);
     380        futex_unlock(&async_futex);
     381
     382        // XXX: This could be replaced with an unlocked version to get rid
     383        // of the unlock-lock pair. I deliberately don't do that because
     384        // further changes would most likely need to revert that optimization.
    380385        fibril_mutex_lock(fm);
    381386
    382         /* async_futex not held after fibril_switch() */
    383387        futex_lock(&async_futex);
    384388        if (wdata.to_event.inlist)
     
    698702        wdata.fid = fibril_get_id();
    699703        list_append(&wdata.wu_event.link, &sem->waiters);
    700         fibril_switch(FIBRIL_TO_MANAGER);
    701 
    702         /* async_futex not held after fibril_switch() */
     704
     705        fibril_switch(FIBRIL_FROM_BLOCKED);
     706        futex_unlock(&async_futex);
    703707}
    704708
  • uspace/lib/c/generic/private/fibril.h

    rb59318e rab6edb6  
    5959typedef enum {
    6060        FIBRIL_PREEMPT,
    61         FIBRIL_TO_MANAGER,
     61        FIBRIL_FROM_BLOCKED,
    6262        FIBRIL_FROM_MANAGER,
    6363        FIBRIL_FROM_DEAD
  • uspace/lib/c/generic/rcu.c

    rb59318e rab6edb6  
    373373                        blocked_fib.is_ready = false;
    374374                        futex_unlock(&rcu.sync_lock.futex);
    375                         fibril_switch(FIBRIL_TO_MANAGER);
     375                        futex_lock(&async_futex);
     376                        fibril_switch(FIBRIL_FROM_BLOCKED);
     377                        futex_unlock(&async_futex);
    376378                        futex_lock(&rcu.sync_lock.futex);
    377379                } while (rcu.sync_lock.locked);
Note: See TracChangeset for help on using the changeset viewer.