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

Changeset 92d34f0b in mainline


Ignore:
Timestamp:
2009-06-11T20:30:59Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
9ae22ba
Parents:
ba2a055
Message:

Implement readers-writer locks for fibrils.

Location:
uspace/lib/libc
Files:
3 edited

Legend:

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

    rba2a055 r92d34f0b  
    9191void fibril_rwlock_initialize(fibril_rwlock_t *frw)
    9292{
    93         fibril_mutex_initialize(&frw->fm);
     93        frw->writers = 0;
     94        frw->readers = 0;
     95        list_initialize(&frw->waiters);
    9496}
    9597
    9698void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
    9799{
    98         fibril_mutex_lock(&frw->fm);
     100        futex_down(&async_futex);
     101        if (frw->writers) {
     102                fibril_t *f = (fibril_t *) fibril_get_id();
     103                f->flags &= ~FIBRIL_WRITER;
     104                list_append(&f->link, &frw->waiters);
     105                fibril_switch(FIBRIL_TO_MANAGER);
     106        } else {
     107                frw->readers++;
     108                futex_up(&async_futex);
     109        }
    99110}
    100111
    101112void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
    102113{
    103         fibril_mutex_lock(&frw->fm);
     114        futex_down(&async_futex);
     115        if (frw->writers || frw->readers) {
     116                fibril_t *f = (fibril_t *) fibril_get_id();
     117                f->flags |= FIBRIL_WRITER;
     118                list_append(&f->link, &frw->waiters);
     119                fibril_switch(FIBRIL_TO_MANAGER);
     120        } else {
     121                frw->writers++;
     122                futex_up(&async_futex);
     123        }
     124}
     125
     126static void _fibril_rwlock_common_unlock(fibril_rwlock_t *frw)
     127{
     128        futex_down(&async_futex);
     129        assert(frw->readers || (frw->writers == 1));
     130        if (frw->readers) {
     131                if (--frw->readers)
     132                        goto out;
     133        } else {
     134                frw->writers--;
     135        }
     136       
     137        assert(!frw->readers && !frw->writers);
     138       
     139        while (!list_empty(&frw->waiters)) {
     140                link_t *tmp = frw->waiters.next;
     141                fibril_t *f = list_get_instance(tmp, fibril_t, link);
     142               
     143                if (f->flags & FIBRIL_WRITER) {
     144                        if (frw->readers)
     145                                break;
     146                        list_remove(&f->link);
     147                        fibril_add_ready((fid_t) f);
     148                        frw->writers++;
     149                        break;
     150                } else {
     151                        list_remove(&f->link);
     152                        fibril_add_ready((fid_t) f);
     153                        frw->readers++;
     154                }
     155        }
     156out:
     157        futex_up(&async_futex);
    104158}
    105159
    106160void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
    107161{
    108         fibril_mutex_unlock(&frw->fm);
     162        _fibril_rwlock_common_unlock(frw);
    109163}
    110164
    111165void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
    112166{
    113         fibril_mutex_unlock(&frw->fm);
     167        _fibril_rwlock_common_unlock(frw);
    114168}
    115169
  • uspace/lib/libc/include/fibril.h

    rba2a055 r92d34f0b  
    4747#endif /* context_set */
    4848
    49 #define FIBRIL_SERIALIZED  1
     49#define FIBRIL_SERIALIZED       1
     50#define FIBRIL_WRITER           2
    5051
    5152typedef enum {
  • uspace/lib/libc/include/fibril_sync.h

    rba2a055 r92d34f0b  
    5656
    5757typedef struct {
    58         fibril_mutex_t fm;
     58        unsigned writers;
     59        unsigned readers;
     60        link_t waiters;
    5961} fibril_rwlock_t;
    6062
    6163#define FIBRIL_RWLOCK_INITIALIZE(name) \
    6264        fibril_rwlock_t name = { \
    63                 .fm = { \
    64                         .counter = 1, \
    65                         .waiters = { \
    66                                 .prev = &name.fm.waiters, \
    67                                 .next = &name.fm.waiters, \
    68                         } \
     65                .readers = 0, \
     66                .writers = 0, \
     67                .waiters = { \
     68                        .prev = &name.waiters, \
     69                        .next = &name.waiters, \
    6970                } \
    7071        }
Note: See TracChangeset for help on using the changeset viewer.