Ignore:
File:
1 edited

Legend:

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

    r84b7384 rd161715  
    3636#include <fibril.h>
    3737#include <async.h>
    38 #include <async_priv.h>
    3938#include <adt/list.h>
    4039#include <futex.h>
     
    4443#include <stacktrace.h>
    4544#include <stdlib.h>
     45#include <stdio.h>
     46#include "private/async.h"
    4647
    4748static void optimize_execution_power(void)
     
    5556         */
    5657        if (atomic_get(&threads_in_ipc_wait) > 0)
    57                 ipc_poke();
    58 }
    59 
    60 static bool check_for_deadlock(fibril_owner_info_t *oi)
    61 {
    62         while (oi && oi->owned_by) {
    63                 if (oi->owned_by == (fibril_t *) fibril_get_id())
    64                         return true;
    65                 oi = oi->owned_by->waits_for;
    66         }
    67 
    68         return false;
     58                async_poke();
    6959}
    7060
     
    8979                oi = oi->owned_by->waits_for;
    9080        }
    91 
    92         abort();
    93 }
     81}
     82
     83
     84static void check_for_deadlock(fibril_owner_info_t *oi)
     85{
     86        while (oi && oi->owned_by) {
     87                if (oi->owned_by == (fibril_t *) fibril_get_id()) {
     88                        print_deadlock(oi);
     89                        abort();
     90                }
     91                oi = oi->owned_by->waits_for;
     92        }
     93}
     94
    9495
    9596void fibril_mutex_initialize(fibril_mutex_t *fm)
     
    103104{
    104105        fibril_t *f = (fibril_t *) fibril_get_id();
     106
     107        if (fibril_get_sercount() != 0)
     108                abort();
    105109
    106110        futex_down(&async_futex);
     
    113117                link_initialize(&wdata.wu_event.link);
    114118                list_append(&wdata.wu_event.link, &fm->waiters);
    115 
    116                 if (check_for_deadlock(&fm->oi))
    117                         print_deadlock(&fm->oi);
     119                check_for_deadlock(&fm->oi);
    118120                f->waits_for = &fm->oi;
    119 
    120121                fibril_switch(FIBRIL_TO_MANAGER);
    121122        } else {
     
    142143static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm)
    143144{
    144         assert(fm->counter <= 0);
    145145        if (fm->counter++ < 0) {
    146146                link_t *tmp;
     
    168168void fibril_mutex_unlock(fibril_mutex_t *fm)
    169169{
     170        assert(fibril_mutex_is_locked(fm));
    170171        futex_down(&async_futex);
    171172        _fibril_mutex_unlock_unsafe(fm);
    172173        futex_up(&async_futex);
     174}
     175
     176bool fibril_mutex_is_locked(fibril_mutex_t *fm)
     177{
     178        bool locked = false;
     179       
     180        futex_down(&async_futex);
     181        if (fm->counter <= 0)
     182                locked = true;
     183        futex_up(&async_futex);
     184       
     185        return locked;
    173186}
    174187
     
    183196void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
    184197{
     198        fibril_t *f = (fibril_t *) fibril_get_id();
     199       
     200        if (fibril_get_sercount() != 0)
     201                abort();
     202
    185203        futex_down(&async_futex);
    186204        if (frw->writers) {
    187                 fibril_t *f = (fibril_t *) fibril_get_id();
    188205                awaiter_t wdata;
    189206
     
    194211                f->flags &= ~FIBRIL_WRITER;
    195212                list_append(&wdata.wu_event.link, &frw->waiters);
     213                check_for_deadlock(&frw->oi);
     214                f->waits_for = &frw->oi;
    196215                fibril_switch(FIBRIL_TO_MANAGER);
    197216        } else {
    198                 frw->readers++;
     217                /* Consider the first reader the owner. */
     218                if (frw->readers++ == 0)
     219                        frw->oi.owned_by = f;
    199220                futex_up(&async_futex);
    200221        }
     
    203224void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
    204225{
     226        fibril_t *f = (fibril_t *) fibril_get_id();
     227       
     228        if (fibril_get_sercount() != 0)
     229                abort();
     230
    205231        futex_down(&async_futex);
    206232        if (frw->writers || frw->readers) {
    207                 fibril_t *f = (fibril_t *) fibril_get_id();
    208233                awaiter_t wdata;
    209234
     
    214239                f->flags |= FIBRIL_WRITER;
    215240                list_append(&wdata.wu_event.link, &frw->waiters);
     241                check_for_deadlock(&frw->oi);
     242                f->waits_for = &frw->oi;
    216243                fibril_switch(FIBRIL_TO_MANAGER);
    217244        } else {
     245                frw->oi.owned_by = f;
    218246                frw->writers++;
    219247                futex_up(&async_futex);
     
    224252{
    225253        futex_down(&async_futex);
    226         assert(frw->readers || (frw->writers == 1));
    227254        if (frw->readers) {
    228                 if (--frw->readers)
     255                if (--frw->readers) {
     256                        if (frw->oi.owned_by == (fibril_t *) fibril_get_id()) {
     257                                /*
     258                                 * If this reader firbril was considered the
     259                                 * owner of this rwlock, clear the ownership
     260                                 * information even if there are still more
     261                                 * readers.
     262                                 *
     263                                 * This is the limitation of the detection
     264                                 * mechanism rooted in the fact that tracking
     265                                 * all readers would require dynamically
     266                                 * allocated memory for keeping linkage info.
     267                                 */
     268                                frw->oi.owned_by = NULL;
     269                        }
    229270                        goto out;
     271                }
    230272        } else {
    231273                frw->writers--;
     
    233275       
    234276        assert(!frw->readers && !frw->writers);
     277       
     278        frw->oi.owned_by = NULL;
    235279       
    236280        while (!list_empty(&frw->waiters)) {
     
    241285                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
    242286                f = (fibril_t *) wdp->fid;
     287               
     288                f->waits_for = NULL;
    243289               
    244290                if (f->flags & FIBRIL_WRITER) {
     
    250296                        fibril_add_ready(wdp->fid);
    251297                        frw->writers++;
     298                        frw->oi.owned_by = f;
    252299                        optimize_execution_power();
    253300                        break;
     
    257304                        list_remove(&wdp->wu_event.link);
    258305                        fibril_add_ready(wdp->fid);
    259                         frw->readers++;
     306                        if (frw->readers++ == 0) {
     307                                /* Consider the first reader the owner. */
     308                                frw->oi.owned_by = f;
     309                        }
    260310                        optimize_execution_power();
    261311                }
     
    267317void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
    268318{
     319        assert(fibril_rwlock_is_read_locked(frw));
    269320        _fibril_rwlock_common_unlock(frw);
    270321}
     
    272323void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
    273324{
     325        assert(fibril_rwlock_is_write_locked(frw));
    274326        _fibril_rwlock_common_unlock(frw);
     327}
     328
     329bool fibril_rwlock_is_read_locked(fibril_rwlock_t *frw)
     330{
     331        bool locked = false;
     332
     333        futex_down(&async_futex);
     334        if (frw->readers)
     335                locked = true;
     336        futex_up(&async_futex);
     337
     338        return locked;
     339}
     340
     341bool fibril_rwlock_is_write_locked(fibril_rwlock_t *frw)
     342{
     343        bool locked = false;
     344
     345        futex_down(&async_futex);
     346        if (frw->writers) {
     347                assert(frw->writers == 1);
     348                locked = true;
     349        }
     350        futex_up(&async_futex);
     351
     352        return locked;
     353}
     354
     355bool fibril_rwlock_is_locked(fibril_rwlock_t *frw)
     356{
     357        return fibril_rwlock_is_read_locked(frw) ||
     358            fibril_rwlock_is_write_locked(frw);
    275359}
    276360
     
    285369{
    286370        awaiter_t wdata;
     371
     372        assert(fibril_mutex_is_locked(fm));
    287373
    288374        if (timeout < 0)
Note: See TracChangeset for help on using the changeset viewer.