Ignore:
Timestamp:
2009-11-16T21:22:54Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5ebdf94
Parents:
fcbd1be (diff), 9c70ed6 (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:

merged with head (unstable)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/fibril_sync.c

    rfcbd1be r1787e527  
    3636#include <fibril.h>
    3737#include <async.h>
     38#include <async_priv.h>
    3839#include <adt/list.h>
    3940#include <futex.h>
     41#include <sys/time.h>
     42#include <errno.h>
    4043#include <assert.h>
     44
     45static void optimize_execution_power(void)
     46{
     47        /*
     48         * When waking up a worker fibril previously blocked in fibril
     49         * synchronization, chances are that there is an idle manager fibril
     50         * waiting for IPC, that could start executing the awakened worker
     51         * fibril right away. We try to detect this and bring the manager
     52         * fibril back to fruitful work.
     53         */
     54        if (atomic_get(&threads_in_ipc_wait) > 0)
     55                ipc_poke();
     56}
    4157
    4258void fibril_mutex_initialize(fibril_mutex_t *fm)
     
    5066        futex_down(&async_futex);
    5167        if (fm->counter-- <= 0) {
    52                 fibril_t *f = (fibril_t *) fibril_get_id();
    53                 list_append(&f->link, &fm->waiters);
     68                awaiter_t wdata;
     69
     70                wdata.fid = fibril_get_id();
     71                wdata.active = false;
     72                wdata.wu_event.inlist = true;
     73                link_initialize(&wdata.wu_event.link);
     74                list_append(&wdata.wu_event.link, &fm->waiters);
    5475                fibril_switch(FIBRIL_TO_MANAGER);
    5576        } else {
     
    7798        if (fm->counter++ < 0) {
    7899                link_t *tmp;
    79                 fibril_t *f;
     100                awaiter_t *wdp;
    80101       
    81102                assert(!list_empty(&fm->waiters));
    82103                tmp = fm->waiters.next;
    83                 f = list_get_instance(tmp, fibril_t, link);
    84                 list_remove(&f->link);
    85                 fibril_add_ready((fid_t) f);
     104                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     105                wdp->active = true;
     106                wdp->wu_event.inlist = false;
     107                list_remove(&wdp->wu_event.link);
     108                fibril_add_ready(wdp->fid);
     109                optimize_execution_power();
    86110        }
    87111}
     
    106130        if (frw->writers) {
    107131                fibril_t *f = (fibril_t *) fibril_get_id();
     132                awaiter_t wdata;
     133
     134                wdata.fid = (fid_t) f;
     135                wdata.active = false;
     136                wdata.wu_event.inlist = true;
     137                link_initialize(&wdata.wu_event.link);
    108138                f->flags &= ~FIBRIL_WRITER;
    109                 list_append(&f->link, &frw->waiters);
     139                list_append(&wdata.wu_event.link, &frw->waiters);
    110140                fibril_switch(FIBRIL_TO_MANAGER);
    111141        } else {
     
    120150        if (frw->writers || frw->readers) {
    121151                fibril_t *f = (fibril_t *) fibril_get_id();
     152                awaiter_t wdata;
     153
     154                wdata.fid = (fid_t) f;
     155                wdata.active = false;
     156                wdata.wu_event.inlist = true;
     157                link_initialize(&wdata.wu_event.link);
    122158                f->flags |= FIBRIL_WRITER;
    123                 list_append(&f->link, &frw->waiters);
     159                list_append(&wdata.wu_event.link, &frw->waiters);
    124160                fibril_switch(FIBRIL_TO_MANAGER);
    125161        } else {
     
    144180        while (!list_empty(&frw->waiters)) {
    145181                link_t *tmp = frw->waiters.next;
    146                 fibril_t *f = list_get_instance(tmp, fibril_t, link);
     182                awaiter_t *wdp;
     183                fibril_t *f;
     184               
     185                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     186                f = (fibril_t *) wdp->fid;
    147187               
    148188                if (f->flags & FIBRIL_WRITER) {
    149189                        if (frw->readers)
    150190                                break;
    151                         list_remove(&f->link);
    152                         fibril_add_ready((fid_t) f);
     191                        wdp->active = true;
     192                        wdp->wu_event.inlist = false;
     193                        list_remove(&wdp->wu_event.link);
     194                        fibril_add_ready(wdp->fid);
    153195                        frw->writers++;
     196                        optimize_execution_power();
    154197                        break;
    155198                } else {
    156                         list_remove(&f->link);
    157                         fibril_add_ready((fid_t) f);
     199                        wdp->active = true;
     200                        wdp->wu_event.inlist = false;
     201                        list_remove(&wdp->wu_event.link);
     202                        fibril_add_ready(wdp->fid);
    158203                        frw->readers++;
     204                        optimize_execution_power();
    159205                }
    160206        }
     
    178224}
    179225
    180 void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
    181 {
    182         fibril_t *f = (fibril_t *) fibril_get_id();
    183 
    184         futex_down(&async_futex);
    185         list_append(&f->link, &fcv->waiters);
     226int
     227fibril_condvar_wait_timeout(fibril_condvar_t *fcv, fibril_mutex_t *fm,
     228    suseconds_t timeout)
     229{
     230        awaiter_t wdata;
     231
     232        if (timeout < 0)
     233                return ETIMEOUT;
     234
     235        wdata.fid = fibril_get_id();
     236        wdata.active = false;
     237       
     238        wdata.to_event.inlist = timeout > 0;
     239        wdata.to_event.occurred = false;
     240        link_initialize(&wdata.to_event.link);
     241
     242        wdata.wu_event.inlist = true;
     243        link_initialize(&wdata.wu_event.link);
     244
     245        futex_down(&async_futex);
     246        if (timeout) {
     247                gettimeofday(&wdata.to_event.expires, NULL);
     248                tv_add(&wdata.to_event.expires, timeout);
     249                async_insert_timeout(&wdata);
     250        }
     251        list_append(&wdata.wu_event.link, &fcv->waiters);
    186252        _fibril_mutex_unlock_unsafe(fm);
    187253        fibril_switch(FIBRIL_TO_MANAGER);
    188254        fibril_mutex_lock(fm);
     255
     256        /* async_futex not held after fibril_switch() */
     257        futex_down(&async_futex);
     258        if (wdata.to_event.inlist)
     259                list_remove(&wdata.to_event.link);
     260        if (wdata.wu_event.inlist)
     261                list_remove(&wdata.wu_event.link);
     262        futex_up(&async_futex);
     263       
     264        return wdata.to_event.occurred ? ETIMEOUT : EOK;
     265}
     266
     267void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
     268{
     269        int rc;
     270
     271        rc = fibril_condvar_wait_timeout(fcv, fm, 0);
     272        assert(rc == EOK);
    189273}
    190274
     
    192276{
    193277        link_t *tmp;
    194         fibril_t *f;
     278        awaiter_t *wdp;
    195279
    196280        futex_down(&async_futex);
    197281        while (!list_empty(&fcv->waiters)) {
    198282                tmp = fcv->waiters.next;
    199                 f = list_get_instance(tmp, fibril_t, link);
    200                 list_remove(&f->link);
    201                 fibril_add_ready((fid_t) f);
    202                 if (once)
    203                         break;
     283                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     284                list_remove(&wdp->wu_event.link);
     285                wdp->wu_event.inlist = false;
     286                if (!wdp->active) {
     287                        wdp->active = true;
     288                        fibril_add_ready(wdp->fid);
     289                        optimize_execution_power();
     290                        if (once)
     291                                break;
     292                }
    204293        }
    205294        futex_up(&async_futex);
Note: See TracChangeset for help on using the changeset viewer.