Fork us on GitHub Follow us on Facebook Follow us on Twitter

Ignore:
Timestamp:
2009-10-11T10:14:34Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
854ad23
Parents:
b6ee5b1
Message:

Experimental support for timeoutable fibril condition variables.

File:
1 edited

Legend:

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

    rb6ee5b1 rcadfa8e  
    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>
    4144
     
    194197}
    195198
    196 void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
    197 {
    198         fibril_t *f = (fibril_t *) fibril_get_id();
    199 
    200         futex_down(&async_futex);
    201         list_append(&f->link, &fcv->waiters);
     199int
     200fibril_condvar_wait_timeout(fibril_condvar_t *fcv, fibril_mutex_t *fm,
     201    suseconds_t timeout)
     202{
     203        awaiter_t wdata;
     204
     205        if (timeout < 0)
     206                return ETIMEOUT;
     207
     208        wdata.fid = fibril_get_id();
     209        wdata.active = false;
     210       
     211        wdata.to_event.inlist = timeout > 0;
     212        wdata.to_event.occurred = false;
     213        link_initialize(&wdata.to_event.link);
     214
     215        wdata.wu_event.inlist = true;
     216        link_initialize(&wdata.wu_event.link);
     217
     218        futex_down(&async_futex);
     219        if (timeout) {
     220                gettimeofday(&wdata.to_event.expires, NULL);
     221                tv_add(&wdata.to_event.expires, timeout);
     222                async_insert_timeout(&wdata);
     223        }
     224        list_append(&wdata.wu_event.link, &fcv->waiters);
    202225        _fibril_mutex_unlock_unsafe(fm);
    203226        fibril_switch(FIBRIL_TO_MANAGER);
    204227        fibril_mutex_lock(fm);
     228
     229        /* async_futex not held after fibril_switch() */
     230        futex_down(&async_futex);
     231        if (wdata.to_event.inlist)
     232                list_remove(&wdata.to_event.link);
     233        if (wdata.wu_event.inlist)
     234                list_remove(&wdata.wu_event.link);
     235        futex_up(&async_futex);
     236       
     237        return wdata.to_event.occurred ? ETIMEOUT : EOK;
     238}
     239
     240void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
     241{
     242        int rc;
     243
     244        rc = fibril_condvar_wait_timeout(fcv, fm, 0);
     245        assert(rc == EOK);
    205246}
    206247
     
    208249{
    209250        link_t *tmp;
    210         fibril_t *f;
     251        awaiter_t *wdp;
    211252
    212253        futex_down(&async_futex);
    213254        while (!list_empty(&fcv->waiters)) {
    214255                tmp = fcv->waiters.next;
    215                 f = list_get_instance(tmp, fibril_t, link);
    216                 list_remove(&f->link);
    217                 fibril_add_ready((fid_t) f);
    218                 optimize_execution_power();
    219                 if (once)
    220                         break;
     256                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     257                list_remove(&wdp->wu_event.link);
     258                wdp->wu_event.inlist = false;
     259                if (!wdp->active) {
     260                        wdp->active = true;
     261                        fibril_add_ready(wdp->fid);
     262                        optimize_execution_power();
     263                        if (once)
     264                                break;
     265                }
    221266        }
    222267        futex_up(&async_futex);
Note: See TracChangeset for help on using the changeset viewer.