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

Changeset cadfa8e in mainline


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.

Location:
uspace/lib/libc
Files:
3 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);
  • uspace/lib/libc/include/async_priv.h

    rb6ee5b1 rcadfa8e  
    5656} to_event_t;
    5757
     58/** Structures of this type are used to track the wakeup events. */
     59typedef struct {
     60        /** If true, this struct is in a synchronization object wait queue. */
     61        bool inlist;
     62       
     63        /** Wait queue linkage. */
     64        link_t link;
     65} wu_event_t;
     66
     67
    5868/** Structures of this type represent a waiting fibril. */
    5969typedef struct {
     
    6676        /** Timeout wait data. */
    6777        to_event_t to_event;
     78        /** Wakeup wait data. */
     79        wu_event_t wu_event;
    6880} awaiter_t;
    6981
  • uspace/lib/libc/include/fibril_sync.h

    rb6ee5b1 rcadfa8e  
    4040#include <adt/list.h>
    4141#include <libarch/tls.h>
     42#include <sys/time.h>
    4243
    4344typedef struct {
     
    9596
    9697extern void fibril_condvar_initialize(fibril_condvar_t *);
     98extern int fibril_condvar_wait_timeout(fibril_condvar_t *, fibril_mutex_t *,
     99    suseconds_t);
    97100extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
    98101extern void fibril_condvar_signal(fibril_condvar_t *);
Note: See TracChangeset for help on using the changeset viewer.