Changeset 8119363 in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2018-06-26T17:35:40Z (7 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:
6e569bf
Parents:
fbfe59d (diff), e768aea (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge some preliminary async/fibril framework changes.

Location:
uspace/lib/c/generic
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/assert.c

    rfbfe59d r8119363  
    3838#include <stacktrace.h>
    3939#include <stdint.h>
     40#include <task.h>
    4041
    4142static atomic_t failed_asserts = { 0 };
     
    4647         * Send the message safely to kio. Nested asserts should not occur.
    4748         */
    48         kio_printf("Assertion failed (%s) in file \"%s\", line %u.\n",
    49             cond, file, line);
     49        kio_printf("Assertion failed (%s) in task %ld, file \"%s\", line %u.\n",
     50            cond, (long) task_get_id(), file, line);
     51
     52        stacktrace_kio_print();
    5053
    5154        /* Sometimes we know in advance that regular printf() would likely fail. */
     
    5861         * Send the message safely to kio. Nested asserts should not occur.
    5962         */
    60         kio_printf("Assertion failed (%s) in file \"%s\", line %u.\n",
    61             cond, file, line);
     63        kio_printf("Assertion failed (%s) in task %ld, file \"%s\", line %u.\n",
     64            cond, (long) task_get_id(), file, line);
     65
     66        stacktrace_kio_print();
    6267
    6368        /*
     
    7277         * assertions.
    7378         */
    74         printf("Assertion failed (%s) in file \"%s\", line %u.\n",
    75             cond, file, line);
     79        kio_printf("Assertion failed (%s) in task %ld, file \"%s\", line %u.\n",
     80            cond, (long) task_get_id(), file, line);
    7681        stacktrace_print();
    7782
  • uspace/lib/c/generic/async/client.c

    rfbfe59d r8119363  
    121121#include <abi/mm/as.h>
    122122#include "../private/libc.h"
     123#include "../private/fibril.h"
    123124
    124125/** Naming service session */
     
    241242        assert(arg);
    242243
    243         futex_down(&async_futex);
     244        futex_lock(&async_futex);
    244245
    245246        amsg_t *msg = (amsg_t *) arg;
     
    266267        }
    267268
    268         futex_up(&async_futex);
     269        futex_unlock(&async_futex);
    269270}
    270271
     
    355356        amsg_t *msg = (amsg_t *) amsgid;
    356357
    357         futex_down(&async_futex);
     358        futex_lock(&async_futex);
    358359
    359360        assert(!msg->forget);
     
    361362
    362363        if (msg->done) {
    363                 futex_up(&async_futex);
     364                futex_unlock(&async_futex);
    364365                goto done;
    365366        }
     
    370371
    371372        /* Leave the async_futex locked when entering this function */
    372         fibril_switch(FIBRIL_TO_MANAGER);
    373 
    374         /* Futex is up automatically after fibril_switch */
     373        fibril_switch(FIBRIL_FROM_BLOCKED);
     374        futex_unlock(&async_futex);
    375375
    376376done:
     
    401401        amsg_t *msg = (amsg_t *) amsgid;
    402402
    403         futex_down(&async_futex);
     403        futex_lock(&async_futex);
    404404
    405405        assert(!msg->forget);
     
    407407
    408408        if (msg->done) {
    409                 futex_up(&async_futex);
     409                futex_unlock(&async_futex);
    410410                goto done;
    411411        }
     
    443443
    444444        /* Leave the async_futex locked when entering this function */
    445         fibril_switch(FIBRIL_TO_MANAGER);
    446 
    447         /* Futex is up automatically after fibril_switch */
     445        fibril_switch(FIBRIL_FROM_BLOCKED);
     446        futex_unlock(&async_futex);
    448447
    449448        if (!msg->done)
     
    475474        assert(!msg->destroyed);
    476475
    477         futex_down(&async_futex);
     476        futex_lock(&async_futex);
    478477
    479478        if (msg->done) {
     
    484483        }
    485484
    486         futex_up(&async_futex);
     485        futex_unlock(&async_futex);
    487486}
    488487
     
    504503        tv_add_diff(&awaiter.to_event.expires, timeout);
    505504
    506         futex_down(&async_futex);
     505        futex_lock(&async_futex);
    507506
    508507        async_insert_timeout(&awaiter);
    509508
    510509        /* Leave the async_futex locked when entering this function */
    511         fibril_switch(FIBRIL_TO_MANAGER);
    512 
    513         /* Futex is up automatically after fibril_switch() */
     510        fibril_switch(FIBRIL_FROM_BLOCKED);
     511        futex_unlock(&async_futex);
    514512}
    515513
  • uspace/lib/c/generic/async/server.c

    rfbfe59d r8119363  
    120120#include <abi/mm/as.h>
    121121#include "../private/libc.h"
     122#include "../private/fibril.h"
    122123
    123124/** Async framework global futex */
     
    431432         * Remove myself from the connection hash table.
    432433         */
    433         futex_down(&async_futex);
     434        futex_lock(&async_futex);
    434435        hash_table_remove(&conn_hash_table, &(conn_key_t){
    435436                .task_id = fibril_connection->in_task_id,
    436437                .phone_hash = fibril_connection->in_phone_hash
    437438        });
    438         futex_up(&async_futex);
     439        futex_unlock(&async_futex);
    439440
    440441        /*
     
    519520        /* Add connection to the connection hash table */
    520521
    521         futex_down(&async_futex);
     522        futex_lock(&async_futex);
    522523        hash_table_insert(&conn_hash_table, &conn->link);
    523         futex_up(&async_futex);
     524        futex_unlock(&async_futex);
    524525
    525526        fibril_add_ready(conn->wdata.fid);
     
    647648        assert(call);
    648649
    649         futex_down(&async_futex);
     650        futex_lock(&async_futex);
    650651
    651652        ht_link_t *link = hash_table_find(&conn_hash_table, &(conn_key_t){
     
    654655        });
    655656        if (!link) {
    656                 futex_up(&async_futex);
     657                futex_unlock(&async_futex);
    657658                return false;
    658659        }
     
    662663        msg_t *msg = malloc(sizeof(*msg));
    663664        if (!msg) {
    664                 futex_up(&async_futex);
     665                futex_unlock(&async_futex);
    665666                return false;
    666667        }
     
    686687        }
    687688
    688         futex_up(&async_futex);
     689        futex_unlock(&async_futex);
    689690        return true;
    690691}
     
    961962        connection_t *conn = fibril_connection;
    962963
    963         futex_down(&async_futex);
     964        futex_lock(&async_futex);
    964965
    965966        if (usecs) {
     
    981982                        memset(call, 0, sizeof(ipc_call_t));
    982983                        IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP);
    983                         futex_up(&async_futex);
     984                        futex_unlock(&async_futex);
    984985                        return conn->close_chandle;
    985986                }
     
    996997                 * case, route_call() will perform the wakeup.
    997998                 */
    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
    10051001                if ((usecs) && (conn->wdata.to_event.occurred) &&
    10061002                    (list_empty(&conn->msg_queue))) {
    10071003                        /* If we timed out -> exit */
    1008                         futex_up(&async_futex);
     1004                        futex_unlock(&async_futex);
    10091005                        return CAP_NIL;
    10101006                }
     
    10191015        free(msg);
    10201016
    1021         futex_up(&async_futex);
     1017        futex_unlock(&async_futex);
    10221018        return chandle;
    10231019}
     
    10701066        assert(call);
    10711067
    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                }
    10751076                return;
    10761077        }
     
    11001101
    11011102/** Fire all timeouts that expired. */
    1102 static void handle_expired_timeouts(void)
    1103 {
     1103static 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
    11041108        struct timeval tv;
    11051109        getuptime(&tv);
    11061110
    1107         futex_down(&async_futex);
     1111        bool fired = false;
    11081112
    11091113        link_t *cur = list_first(&timeout_list);
     
    11121116                    list_get_instance(cur, awaiter_t, to_event.link);
    11131117
    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                }
    11161126
    11171127                list_remove(&waiter->to_event.link);
     
    11261136                        waiter->active = true;
    11271137                        fibril_add_ready(waiter->fid);
     1138                        fired = true;
    11281139                }
    11291140
     
    11311142        }
    11321143
    1133         futex_up(&async_futex);
     1144        if (fired) {
     1145                *flags = SYNCH_FLAGS_NON_BLOCKING;
     1146                return 0;
     1147        }
     1148
     1149        return SYNCH_NO_TIMEOUT;
    11341150}
    11351151
     
    11421158{
    11431159        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
    11561168                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);
    11891171
    11901172                atomic_inc(&threads_in_ipc_wait);
    11911173
    11921174                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);
    11941176
    11951177                atomic_dec(&threads_in_ipc_wait);
    11961178
    11971179                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 
    12111180                handle_call(call.cap_handle, &call);
    12121181        }
     
    12251194static errno_t async_manager_fibril(void *arg)
    12261195{
    1227         futex_up(&async_futex);
    1228 
    1229         /*
    1230          * async_futex is always locked when entering manager
    1231          */
    12321196        async_manager_worker();
    1233 
    12341197        return 0;
    12351198}
     
    18841847}
    18851848
     1849_Noreturn void async_manager(void)
     1850{
     1851        futex_lock(&async_futex);
     1852        fibril_switch(FIBRIL_FROM_DEAD);
     1853        __builtin_unreachable();
     1854}
     1855
    18861856/** @}
    18871857 */
  • uspace/lib/c/generic/fibril.c

    rfbfe59d r8119363  
    4949#include <async.h>
    5050
    51 #ifdef FUTEX_UPGRADABLE
    52 #include <rcu.h>
    53 #endif
     51#include "private/fibril.h"
     52
    5453
    5554/**
     
    7271static void fibril_main(void)
    7372{
    74         /* fibril_futex is locked when a fibril is first started. */
    75         futex_unlock(&fibril_futex);
    76 
    77         fibril_t *fibril = __tcb_get()->fibril_data;
    78 
    79 #ifdef FUTEX_UPGRADABLE
    80         rcu_register_fibril();
    81 #endif
     73        /* fibril_futex and async_futex are locked when a fibril is started. */
     74        futex_unlock(&fibril_futex);
     75        futex_unlock(&async_futex);
     76
     77        fibril_t *fibril = fibril_self();
    8278
    8379        /* Call the implementing function. */
    8480        fibril->retval = fibril->func(fibril->arg);
    8581
    86         futex_down(&async_futex);
     82        futex_lock(&async_futex);
    8783        fibril_switch(FIBRIL_FROM_DEAD);
    8884        /* Not reached */
     
    9894                return NULL;
    9995
    100         fibril_t *fibril = malloc(sizeof(fibril_t));
     96        fibril_t *fibril = calloc(1, sizeof(fibril_t));
    10197        if (!fibril) {
    10298                tls_free(tcb);
     
    106102        tcb->fibril_data = fibril;
    107103        fibril->tcb = tcb;
    108 
    109         fibril->func = NULL;
    110         fibril->arg = NULL;
    111         fibril->stack = NULL;
    112         fibril->clean_after_me = NULL;
    113         fibril->retval = 0;
    114         fibril->flags = 0;
    115 
    116         fibril->waits_for = NULL;
    117104
    118105        /*
     
    141128/** Switch from the current fibril.
    142129 *
    143  * If stype is FIBRIL_TO_MANAGER or FIBRIL_FROM_DEAD, the async_futex must
    144  * be held.
     130 * The async_futex must be held when entering this function,
     131 * and is still held on return.
    145132 *
    146133 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
     
    154141int fibril_switch(fibril_switch_type_t stype)
    155142{
     143        /* Make sure the async_futex is held. */
     144        futex_assert_is_locked(&async_futex);
     145
    156146        futex_lock(&fibril_futex);
    157147
    158         fibril_t *srcf = __tcb_get()->fibril_data;
     148        fibril_t *srcf = fibril_self();
    159149        fibril_t *dstf = NULL;
    160150
    161151        /* Choose a new fibril to run */
    162         switch (stype) {
    163         case FIBRIL_TO_MANAGER:
    164         case FIBRIL_FROM_DEAD:
    165                 /* Make sure the async_futex is held. */
    166                 assert((atomic_signed_t) async_futex.val.count <= 0);
     152        if (list_empty(&ready_list)) {
     153                if (stype == FIBRIL_PREEMPT || stype == FIBRIL_FROM_MANAGER) {
     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                }
    167159
    168160                /* If we are going to manager and none exists, create it */
     
    175167                dstf = list_get_instance(list_first(&manager_list),
    176168                    fibril_t, link);
    177 
    178                 if (stype == FIBRIL_FROM_DEAD)
    179                         dstf->clean_after_me = srcf;
    180                 break;
    181         case FIBRIL_PREEMPT:
    182         case FIBRIL_FROM_MANAGER:
    183                 if (list_empty(&ready_list)) {
    184                         futex_unlock(&fibril_futex);
    185                         return 0;
    186                 }
    187 
     169        } else {
    188170                dstf = list_get_instance(list_first(&ready_list), fibril_t,
    189171                    link);
    190                 break;
    191         }
     172        }
     173
    192174        list_remove(&dstf->link);
     175        if (stype == FIBRIL_FROM_DEAD)
     176                dstf->clean_after_me = srcf;
    193177
    194178        /* Put the current fibril into the correct run list */
     
    201185                break;
    202186        case FIBRIL_FROM_DEAD:
     187        case FIBRIL_FROM_BLOCKED:
    203188                // Nothing.
    204189                break;
    205         case FIBRIL_TO_MANAGER:
    206                 /*
    207                  * Don't put the current fibril into any list, it should
    208                  * already be somewhere, or it will be lost.
    209                  */
    210                 break;
    211         }
    212 
    213 #ifdef FUTEX_UPGRADABLE
    214         if (stype == FIBRIL_FROM_DEAD) {
    215                 rcu_deregister_fibril();
    216         }
    217 #endif
     190        }
     191
     192        /* Bookkeeping. */
     193        futex_give_to(&fibril_futex, dstf);
     194        futex_give_to(&async_futex, dstf);
    218195
    219196        /* Swap to the next fibril. */
     
    345322}
    346323
     324fibril_t *fibril_self(void)
     325{
     326        return __tcb_get()->fibril_data;
     327}
     328
    347329/** Return fibril id of the currently running fibril.
    348330 *
     
    352334fid_t fibril_get_id(void)
    353335{
    354         return (fid_t) __tcb_get()->fibril_data;
     336        return (fid_t) fibril_self();
     337}
     338
     339void fibril_yield(void)
     340{
     341        futex_lock(&async_futex);
     342        (void) fibril_switch(FIBRIL_PREEMPT);
     343        futex_unlock(&async_futex);
    355344}
    356345
  • uspace/lib/c/generic/fibril_synch.c

    rfbfe59d r8119363  
    4545#include <stdio.h>
    4646#include "private/async.h"
     47#include "private/fibril.h"
    4748
    4849static void optimize_execution_power(void)
     
    105106        fibril_t *f = (fibril_t *) fibril_get_id();
    106107
    107         futex_down(&async_futex);
     108        futex_lock(&async_futex);
    108109        if (fm->counter-- <= 0) {
    109110                awaiter_t wdata;
     
    115116                check_for_deadlock(&fm->oi);
    116117                f->waits_for = &fm->oi;
    117                 fibril_switch(FIBRIL_TO_MANAGER);
     118                fibril_switch(FIBRIL_FROM_BLOCKED);
    118119        } else {
    119120                fm->oi.owned_by = f;
    120                 futex_up(&async_futex);
    121         }
     121        }
     122        futex_unlock(&async_futex);
    122123}
    123124
     
    126127        bool locked = false;
    127128
    128         futex_down(&async_futex);
     129        futex_lock(&async_futex);
    129130        if (fm->counter > 0) {
    130131                fm->counter--;
     
    132133                locked = true;
    133134        }
    134         futex_up(&async_futex);
     135        futex_unlock(&async_futex);
    135136
    136137        return locked;
     
    165166{
    166167        assert(fibril_mutex_is_locked(fm));
    167         futex_down(&async_futex);
     168        futex_lock(&async_futex);
    168169        _fibril_mutex_unlock_unsafe(fm);
    169         futex_up(&async_futex);
     170        futex_unlock(&async_futex);
    170171}
    171172
     
    174175        bool locked = false;
    175176
    176         futex_down(&async_futex);
     177        futex_lock(&async_futex);
    177178        if (fm->counter <= 0)
    178179                locked = true;
    179         futex_up(&async_futex);
     180        futex_unlock(&async_futex);
    180181
    181182        return locked;
     
    194195        fibril_t *f = (fibril_t *) fibril_get_id();
    195196
    196         futex_down(&async_futex);
     197        futex_lock(&async_futex);
    197198        if (frw->writers) {
    198199                awaiter_t wdata;
     
    201202                wdata.fid = (fid_t) f;
    202203                wdata.wu_event.inlist = true;
    203                 f->flags &= ~FIBRIL_WRITER;
     204                f->is_writer = false;
    204205                list_append(&wdata.wu_event.link, &frw->waiters);
    205206                check_for_deadlock(&frw->oi);
    206207                f->waits_for = &frw->oi;
    207                 fibril_switch(FIBRIL_TO_MANAGER);
     208                fibril_switch(FIBRIL_FROM_BLOCKED);
    208209        } else {
    209210                /* Consider the first reader the owner. */
    210211                if (frw->readers++ == 0)
    211212                        frw->oi.owned_by = f;
    212                 futex_up(&async_futex);
    213         }
     213        }
     214        futex_unlock(&async_futex);
    214215}
    215216
     
    218219        fibril_t *f = (fibril_t *) fibril_get_id();
    219220
    220         futex_down(&async_futex);
     221        futex_lock(&async_futex);
    221222        if (frw->writers || frw->readers) {
    222223                awaiter_t wdata;
     
    225226                wdata.fid = (fid_t) f;
    226227                wdata.wu_event.inlist = true;
    227                 f->flags |= FIBRIL_WRITER;
     228                f->is_writer = true;
    228229                list_append(&wdata.wu_event.link, &frw->waiters);
    229230                check_for_deadlock(&frw->oi);
    230231                f->waits_for = &frw->oi;
    231                 fibril_switch(FIBRIL_TO_MANAGER);
     232                fibril_switch(FIBRIL_FROM_BLOCKED);
    232233        } else {
    233234                frw->oi.owned_by = f;
    234235                frw->writers++;
    235                 futex_up(&async_futex);
    236         }
     236        }
     237        futex_unlock(&async_futex);
    237238}
    238239
    239240static void _fibril_rwlock_common_unlock(fibril_rwlock_t *frw)
    240241{
    241         futex_down(&async_futex);
     242        futex_lock(&async_futex);
    242243        if (frw->readers) {
    243244                if (--frw->readers) {
     
    276277                f->waits_for = NULL;
    277278
    278                 if (f->flags & FIBRIL_WRITER) {
     279                if (f->is_writer) {
    279280                        if (frw->readers)
    280281                                break;
     
    300301        }
    301302out:
    302         futex_up(&async_futex);
     303        futex_unlock(&async_futex);
    303304}
    304305
     
    319320        bool locked = false;
    320321
    321         futex_down(&async_futex);
     322        futex_lock(&async_futex);
    322323        if (frw->readers)
    323324                locked = true;
    324         futex_up(&async_futex);
     325        futex_unlock(&async_futex);
    325326
    326327        return locked;
     
    331332        bool locked = false;
    332333
    333         futex_down(&async_futex);
     334        futex_lock(&async_futex);
    334335        if (frw->writers) {
    335336                assert(frw->writers == 1);
    336337                locked = true;
    337338        }
    338         futex_up(&async_futex);
     339        futex_unlock(&async_futex);
    339340
    340341        return locked;
     
    368369        wdata.wu_event.inlist = true;
    369370
    370         futex_down(&async_futex);
     371        futex_lock(&async_futex);
    371372        if (timeout) {
    372373                getuptime(&wdata.to_event.expires);
     
    376377        list_append(&wdata.wu_event.link, &fcv->waiters);
    377378        _fibril_mutex_unlock_unsafe(fm);
    378         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.
    379385        fibril_mutex_lock(fm);
    380386
    381         /* async_futex not held after fibril_switch() */
    382         futex_down(&async_futex);
     387        futex_lock(&async_futex);
    383388        if (wdata.to_event.inlist)
    384389                list_remove(&wdata.to_event.link);
    385390        if (wdata.wu_event.inlist)
    386391                list_remove(&wdata.wu_event.link);
    387         futex_up(&async_futex);
     392        futex_unlock(&async_futex);
    388393
    389394        return wdata.to_event.occurred ? ETIMEOUT : EOK;
     
    403408        awaiter_t *wdp;
    404409
    405         futex_down(&async_futex);
     410        futex_lock(&async_futex);
    406411        while (!list_empty(&fcv->waiters)) {
    407412                tmp = list_first(&fcv->waiters);
     
    417422                }
    418423        }
    419         futex_up(&async_futex);
     424        futex_unlock(&async_futex);
    420425}
    421426
     
    656661void fibril_semaphore_up(fibril_semaphore_t *sem)
    657662{
    658         futex_down(&async_futex);
     663        futex_lock(&async_futex);
    659664        sem->count++;
    660665
    661666        if (sem->count > 0) {
    662                 futex_up(&async_futex);
     667                futex_unlock(&async_futex);
    663668                return;
    664669        }
     
    668673        list_remove(tmp);
    669674
    670         futex_up(&async_futex);
     675        futex_unlock(&async_futex);
    671676
    672677        awaiter_t *wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     
    684689void fibril_semaphore_down(fibril_semaphore_t *sem)
    685690{
    686         futex_down(&async_futex);
     691        futex_lock(&async_futex);
    687692        sem->count--;
    688693
    689694        if (sem->count >= 0) {
    690                 futex_up(&async_futex);
     695                futex_unlock(&async_futex);
    691696                return;
    692697        }
     
    697702        wdata.fid = fibril_get_id();
    698703        list_append(&wdata.wu_event.link, &sem->waiters);
    699         fibril_switch(FIBRIL_TO_MANAGER);
    700 
    701         /* async_futex not held after fibril_switch() */
     704
     705        fibril_switch(FIBRIL_FROM_BLOCKED);
     706        futex_unlock(&async_futex);
    702707}
    703708
  • uspace/lib/c/generic/futex.c

    rfbfe59d r8119363  
    3434
    3535#include <futex.h>
     36
     37#include <assert.h>
    3638#include <atomic.h>
     39#include <fibril.h>
     40#include <io/kio.h>
     41
     42#include "private/fibril.h"
     43
     44//#define DPRINTF(...) kio_printf(__VA_ARGS__)
     45#define DPRINTF(...) ((void)0)
    3746
    3847/** Initialize futex counter.
     
    4756}
    4857
     58#ifdef CONFIG_DEBUG_FUTEX
    4959
    50 #ifdef FUTEX_UPGRADABLE
     60void __futex_assert_is_locked(futex_t *futex, const char *name)
     61{
     62        void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     63        fibril_t *self = (fibril_t *) fibril_get_id();
     64        if (owner != self) {
     65                DPRINTF("Assertion failed: %s (%p) is not locked by fibril %p (instead locked by fibril %p).\n", name, futex, self, owner);
     66        }
     67        assert(owner == self);
     68}
    5169
    52 int _upgrade_futexes = 0;
    53 static futex_t upg_and_wait_futex = FUTEX_INITIALIZER;
     70void __futex_assert_is_not_locked(futex_t *futex, const char *name)
     71{
     72        void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     73        fibril_t *self = (fibril_t *) fibril_get_id();
     74        if (owner == self) {
     75                DPRINTF("Assertion failed: %s (%p) is already locked by fibril %p.\n", name, futex, self);
     76        }
     77        assert(owner != self);
     78}
    5479
    55 void futex_upgrade_all_and_wait(void)
     80void __futex_lock(futex_t *futex, const char *name)
    5681{
    57         futex_down(&upg_and_wait_futex);
     82        /* We use relaxed atomics to avoid violating C11 memory model.
     83         * They should compile to regular load/stores, but simple assignments
     84         * would be UB by definition.
     85         */
    5886
    59         if (!_upgrade_futexes) {
    60                 rcu_assign(_upgrade_futexes, 1);
    61                 _rcu_synchronize(BM_BLOCK_THREAD);
     87        fibril_t *self = (fibril_t *) fibril_get_id();
     88        DPRINTF("Locking futex %s (%p) by fibril %p.\n", name, futex, self);
     89        __futex_assert_is_not_locked(futex, name);
     90        futex_down(futex);
     91
     92        void *prev_owner = __atomic_exchange_n(&futex->owner, self, __ATOMIC_RELAXED);
     93        assert(prev_owner == NULL);
     94
     95        atomic_inc(&self->futex_locks);
     96}
     97
     98void __futex_unlock(futex_t *futex, const char *name)
     99{
     100        fibril_t *self = (fibril_t *) fibril_get_id();
     101        DPRINTF("Unlocking futex %s (%p) by fibril %p.\n", name, futex, self);
     102        __futex_assert_is_locked(futex, name);
     103        __atomic_store_n(&futex->owner, NULL, __ATOMIC_RELAXED);
     104        atomic_dec(&self->futex_locks);
     105        futex_up(futex);
     106}
     107
     108bool __futex_trylock(futex_t *futex, const char *name)
     109{
     110        fibril_t *self = (fibril_t *) fibril_get_id();
     111        bool success = futex_trydown(futex);
     112        if (success) {
     113                void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     114                assert(owner == NULL);
     115
     116                __atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED);
     117
     118                atomic_inc(&self->futex_locks);
     119
     120                DPRINTF("Trylock on futex %s (%p) by fibril %p succeeded.\n", name, futex, self);
     121        } else {
     122                DPRINTF("Trylock on futex %s (%p) by fibril %p failed.\n", name, futex, self);
    62123        }
    63124
    64         futex_up(&upg_and_wait_futex);
     125        return success;
     126}
     127
     128void __futex_give_to(futex_t *futex, void *new_owner, const char *name)
     129{
     130        fibril_t *self = fibril_self();
     131        fibril_t *no = new_owner;
     132        DPRINTF("Passing futex %s (%p) from fibril %p to fibril %p.\n", name, futex, self, no);
     133
     134        __futex_assert_is_locked(futex, name);
     135        atomic_dec(&self->futex_locks);
     136        atomic_inc(&no->futex_locks);
     137        __atomic_store_n(&futex->owner, new_owner, __ATOMIC_RELAXED);
    65138}
    66139
  • uspace/lib/c/generic/inet/host.c

    rfbfe59d r8119363  
    3535 */
    3636
     37#include <assert.h>
    3738#include <errno.h>
    3839#include <inet/addr.h>
  • uspace/lib/c/generic/inet/hostport.c

    rfbfe59d r8119363  
    3636 */
    3737
     38#include <assert.h>
    3839#include <errno.h>
    3940#include <inet/addr.h>
  • uspace/lib/c/generic/libc.c

    rfbfe59d r8119363  
    5555#include "private/malloc.h"
    5656#include "private/io.h"
    57 
    58 #ifdef FUTEX_UPGRADABLE
    59 #include <rcu.h>
    60 #endif
     57#include "private/fibril.h"
    6158
    6259#ifdef CONFIG_RTLD
     
    8986
    9087        __tcb_set(fibril->tcb);
    91 
    92 
    93 #ifdef FUTEX_UPGRADABLE
    94         rcu_register_fibril();
    95 #endif
    9688
    9789        __async_server_init();
  • uspace/lib/c/generic/rcu.c

    rfbfe59d r8119363  
    8282#include <thread.h>
    8383
     84#include "private/fibril.h"
     85
    8486
    8587/** RCU sleeps for RCU_SLEEP_MS before polling an active RCU reader again. */
     
    148150
    149151
    150 static void wait_for_readers(size_t reader_group, blocking_mode_t blocking_mode);
     152static void wait_for_readers(size_t reader_group);
    151153static void force_mb_in_all_threads(void);
    152154static bool is_preexisting_reader(const fibril_rcu_data_t *fib, size_t group);
    153155
    154 static void lock_sync(blocking_mode_t blocking_mode);
     156static void lock_sync(void);
    155157static void unlock_sync(void);
    156 static void sync_sleep(blocking_mode_t blocking_mode);
     158static void sync_sleep(void);
    157159
    158160static bool is_in_group(size_t nesting_cnt, size_t group);
     
    170172        assert(!fibril_rcu.registered);
    171173
    172         futex_down(&rcu.list_futex);
     174        futex_lock(&rcu.list_futex);
    173175        list_append(&fibril_rcu.link, &rcu.fibrils_list);
    174         futex_up(&rcu.list_futex);
     176        futex_unlock(&rcu.list_futex);
    175177
    176178        fibril_rcu.registered = true;
     
    195197        fibril_rcu.nesting_cnt = 0;
    196198
    197         futex_down(&rcu.list_futex);
     199        futex_lock(&rcu.list_futex);
    198200        list_remove(&fibril_rcu.link);
    199         futex_up(&rcu.list_futex);
     201        futex_unlock(&rcu.list_futex);
    200202
    201203        fibril_rcu.registered = false;
     
    240242
    241243/** Blocks until all preexisting readers exit their critical sections. */
    242 void _rcu_synchronize(blocking_mode_t blocking_mode)
     244void rcu_synchronize(void)
    243245{
    244246        assert(!rcu_read_locked());
     
    250252        size_t gp_in_progress = ACCESS_ONCE(rcu.cur_gp);
    251253
    252         lock_sync(blocking_mode);
     254        lock_sync();
    253255
    254256        /*
     
    298300
    299301        size_t new_reader_group = get_other_group(rcu.reader_group);
    300         wait_for_readers(new_reader_group, blocking_mode);
     302        wait_for_readers(new_reader_group);
    301303
    302304        /* Separates waiting for readers in new_reader_group from group flip. */
     
    310312        memory_barrier();
    311313
    312         wait_for_readers(old_reader_group, blocking_mode);
     314        wait_for_readers(old_reader_group);
    313315
    314316        /* MB_FORCE_U  */
     
    330332
    331333/** Waits for readers of reader_group to exit their readers sections. */
    332 static void wait_for_readers(size_t reader_group, blocking_mode_t blocking_mode)
    333 {
    334         futex_down(&rcu.list_futex);
     334static void wait_for_readers(size_t reader_group)
     335{
     336        futex_lock(&rcu.list_futex);
    335337
    336338        list_t quiescent_fibrils;
     
    343345
    344346                        if (is_preexisting_reader(fib, reader_group)) {
    345                                 futex_up(&rcu.list_futex);
    346                                 sync_sleep(blocking_mode);
    347                                 futex_down(&rcu.list_futex);
     347                                futex_unlock(&rcu.list_futex);
     348                                sync_sleep();
     349                                futex_lock(&rcu.list_futex);
    348350                                /* Break to while loop. */
    349351                                break;
     
    356358
    357359        list_concat(&rcu.fibrils_list, &quiescent_fibrils);
    358         futex_up(&rcu.list_futex);
    359 }
    360 
    361 static void lock_sync(blocking_mode_t blocking_mode)
    362 {
    363         futex_down(&rcu.sync_lock.futex);
     360        futex_unlock(&rcu.list_futex);
     361}
     362
     363static void lock_sync(void)
     364{
     365        futex_lock(&rcu.sync_lock.futex);
    364366        if (rcu.sync_lock.locked) {
    365                 if (blocking_mode == BM_BLOCK_FIBRIL) {
    366                         blocked_fibril_t blocked_fib;
    367                         blocked_fib.id = fibril_get_id();
    368 
    369                         list_append(&blocked_fib.link, &rcu.sync_lock.blocked_fibrils);
    370 
    371                         do {
    372                                 blocked_fib.is_ready = false;
    373                                 futex_up(&rcu.sync_lock.futex);
    374                                 fibril_switch(FIBRIL_TO_MANAGER);
    375                                 futex_down(&rcu.sync_lock.futex);
    376                         } while (rcu.sync_lock.locked);
    377 
    378                         list_remove(&blocked_fib.link);
    379                         rcu.sync_lock.locked = true;
    380                 } else {
    381                         assert(blocking_mode == BM_BLOCK_THREAD);
    382                         rcu.sync_lock.blocked_thread_cnt++;
    383                         futex_up(&rcu.sync_lock.futex);
    384                         futex_down(&rcu.sync_lock.futex_blocking_threads);
    385                 }
     367                blocked_fibril_t blocked_fib;
     368                blocked_fib.id = fibril_get_id();
     369
     370                list_append(&blocked_fib.link, &rcu.sync_lock.blocked_fibrils);
     371
     372                do {
     373                        blocked_fib.is_ready = false;
     374                        futex_unlock(&rcu.sync_lock.futex);
     375                        futex_lock(&async_futex);
     376                        fibril_switch(FIBRIL_FROM_BLOCKED);
     377                        futex_unlock(&async_futex);
     378                        futex_lock(&rcu.sync_lock.futex);
     379                } while (rcu.sync_lock.locked);
     380
     381                list_remove(&blocked_fib.link);
     382                rcu.sync_lock.locked = true;
    386383        } else {
    387384                rcu.sync_lock.locked = true;
     
    399396        if (0 < rcu.sync_lock.blocked_thread_cnt) {
    400397                --rcu.sync_lock.blocked_thread_cnt;
    401                 futex_up(&rcu.sync_lock.futex_blocking_threads);
     398                futex_unlock(&rcu.sync_lock.futex_blocking_threads);
    402399        } else {
    403400                /* Unlock but wake up any fibrils waiting for the lock. */
     
    414411
    415412                rcu.sync_lock.locked = false;
    416                 futex_up(&rcu.sync_lock.futex);
     413                futex_unlock(&rcu.sync_lock.futex);
    417414        }
    418415}
    419416
    420 static void sync_sleep(blocking_mode_t blocking_mode)
     417static void sync_sleep(void)
    421418{
    422419        assert(rcu.sync_lock.locked);
     
    425422         * but keep sync locked.
    426423         */
    427         futex_up(&rcu.sync_lock.futex);
    428 
    429         if (blocking_mode == BM_BLOCK_FIBRIL) {
    430                 async_usleep(RCU_SLEEP_MS * 1000);
    431         } else {
    432                 thread_usleep(RCU_SLEEP_MS * 1000);
    433         }
    434 
    435         futex_down(&rcu.sync_lock.futex);
     424        futex_unlock(&rcu.sync_lock.futex);
     425        async_usleep(RCU_SLEEP_MS * 1000);
     426        futex_lock(&rcu.sync_lock.futex);
    436427}
    437428
  • uspace/lib/c/generic/stacktrace.c

    rfbfe59d r8119363  
    3939#include <stdint.h>
    4040#include <errno.h>
     41#include <io/kio.h>
    4142
    4243static errno_t stacktrace_read_uintptr(void *arg, uintptr_t addr, uintptr_t *data);
    4344
    4445static stacktrace_ops_t basic_ops = {
    45         .read_uintptr = stacktrace_read_uintptr
     46        .read_uintptr = stacktrace_read_uintptr,
     47        .printf = printf,
     48};
     49
     50static stacktrace_ops_t kio_ops = {
     51        .read_uintptr = stacktrace_read_uintptr,
     52        .printf = kio_printf,
    4653};
    4754
     
    5764
    5865        while (stacktrace_fp_valid(&st, fp)) {
    59                 printf("%p: %p()\n", (void *) fp, (void *) pc);
     66                ops->printf("%p: %p()\n", (void *) fp, (void *) pc);
    6067                rc =  stacktrace_ra_get(&st, fp, &pc);
    6168                if (rc != EOK)
     
    7178{
    7279        stacktrace_print_generic(&basic_ops, NULL, fp, pc);
     80}
     81
     82void stacktrace_kio_print(void)
     83{
     84        stacktrace_prepare();
     85        stacktrace_print_generic(&kio_ops, NULL, stacktrace_fp_get(), stacktrace_pc_get());
     86
     87        /*
     88         * Prevent the tail call optimization of the previous call by
     89         * making it a non-tail call.
     90         */
     91
     92        kio_printf("-- end of stack trace --\n");
    7393}
    7494
  • uspace/lib/c/generic/thread.c

    rfbfe59d r8119363  
    4646#include <as.h>
    4747#include "private/thread.h"
    48 
    49 #ifdef FUTEX_UPGRADABLE
    50 #include <rcu.h>
    51 #endif
    52 
     48#include "private/fibril.h"
    5349
    5450/** Main thread function.
     
    6864
    6965        __tcb_set(fibril->tcb);
    70 
    71 #ifdef FUTEX_UPGRADABLE
    72         rcu_register_fibril();
    73         futex_upgrade_all_and_wait();
    74 #endif
    7566
    7667        uarg->uspace_thread_function(uarg->uspace_thread_arg);
     
    8475        /* If there is a manager, destroy it */
    8576        async_destroy_manager();
    86 
    87 #ifdef FUTEX_UPGRADABLE
    88         rcu_deregister_fibril();
    89 #endif
    9077
    9178        fibril_teardown(fibril, false);
  • uspace/lib/c/generic/time.c

    rfbfe59d r8119363  
    5151#include <loc.h>
    5252#include <device/clock_dev.h>
    53 #include <thread.h>
    5453
    5554#define ASCTIME_BUF_LEN  26
     
    487486 * @param tv2 Second timeval.
    488487 */
    489 void tv_add(struct timeval *tv1, struct timeval *tv2)
     488void tv_add(struct timeval *tv1, const struct timeval *tv2)
    490489{
    491490        tv1->tv_sec += tv2->tv_sec;
     
    503502 *
    504503 */
    505 suseconds_t tv_sub_diff(struct timeval *tv1, struct timeval *tv2)
     504suseconds_t tv_sub_diff(const struct timeval *tv1, const struct timeval *tv2)
    506505{
    507506        return (tv1->tv_usec - tv2->tv_usec) +
     
    515514 *
    516515 */
    517 void tv_sub(struct timeval *tv1, struct timeval *tv2)
     516void tv_sub(struct timeval *tv1, const struct timeval *tv2)
    518517{
    519518        tv1->tv_sec -= tv2->tv_sec;
     
    531530 *
    532531 */
    533 int tv_gt(struct timeval *tv1, struct timeval *tv2)
     532int tv_gt(const struct timeval *tv1, const struct timeval *tv2)
    534533{
    535534        if (tv1->tv_sec > tv2->tv_sec)
     
    551550 *
    552551 */
    553 int tv_gteq(struct timeval *tv1, struct timeval *tv2)
     552int tv_gteq(const struct timeval *tv1, const struct timeval *tv2)
    554553{
    555554        if (tv1->tv_sec > tv2->tv_sec)
Note: See TracChangeset for help on using the changeset viewer.