Ignore:
File:
1 edited

Legend:

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

    r63f8966 r9414abc  
    4242#include <errno.h>
    4343#include <assert.h>
     44#include <stacktrace.h>
     45#include <stdlib.h>
    4446
    4547static void optimize_execution_power(void)
     
    5658}
    5759
     60static void print_deadlock(fibril_owner_info_t *oi)
     61{
     62        fibril_t *f = (fibril_t *) fibril_get_id();
     63
     64        printf("Deadlock detected.\n");
     65        stacktrace_print();
     66
     67        printf("Fibril %p waits for primitive %p.\n", f, oi);
     68
     69        while (oi && oi->owned_by) {
     70                printf("Primitive %p is owned by fibril %p.\n",
     71                    oi, oi->owned_by);
     72                if (oi->owned_by == f)
     73                        break;
     74                stacktrace_print_fp_pc(context_get_fp(&oi->owned_by->ctx),
     75                    oi->owned_by->ctx.pc);
     76                printf("Fibril %p waits for primitive %p.\n",
     77                     oi->owned_by, oi->owned_by->waits_for);
     78                oi = oi->owned_by->waits_for;
     79        }
     80}
     81
     82
     83static void check_for_deadlock(fibril_owner_info_t *oi)
     84{
     85        while (oi && oi->owned_by) {
     86                if (oi->owned_by == (fibril_t *) fibril_get_id()) {
     87                        print_deadlock(oi);
     88                        abort();
     89                }
     90                oi = oi->owned_by->waits_for;
     91        }
     92}
     93
     94
    5895void fibril_mutex_initialize(fibril_mutex_t *fm)
    5996{
     97        fm->oi.owned_by = NULL;
    6098        fm->counter = 1;
    6199        list_initialize(&fm->waiters);
     
    64102void fibril_mutex_lock(fibril_mutex_t *fm)
    65103{
     104        fibril_t *f = (fibril_t *) fibril_get_id();
     105
    66106        futex_down(&async_futex);
    67107        if (fm->counter-- <= 0) {
     
    73113                link_initialize(&wdata.wu_event.link);
    74114                list_append(&wdata.wu_event.link, &fm->waiters);
     115                check_for_deadlock(&fm->oi);
     116                f->waits_for = &fm->oi;
    75117                fibril_switch(FIBRIL_TO_MANAGER);
    76118        } else {
     119                fm->oi.owned_by = f;
    77120                futex_up(&async_futex);
    78121        }
     
    86129        if (fm->counter > 0) {
    87130                fm->counter--;
     131                fm->oi.owned_by = (fibril_t *) fibril_get_id();
    88132                locked = true;
    89133        }
     
    99143                link_t *tmp;
    100144                awaiter_t *wdp;
     145                fibril_t *f;
    101146       
    102147                assert(!list_empty(&fm->waiters));
     
    105150                wdp->active = true;
    106151                wdp->wu_event.inlist = false;
     152
     153                f = (fibril_t *) wdp->fid;
     154                fm->oi.owned_by = f;
     155                f->waits_for = NULL;
     156
    107157                list_remove(&wdp->wu_event.link);
    108158                fibril_add_ready(wdp->fid);
    109159                optimize_execution_power();
     160        } else {
     161                fm->oi.owned_by = NULL;
    110162        }
    111163}
     
    120172void fibril_rwlock_initialize(fibril_rwlock_t *frw)
    121173{
     174        frw->oi.owned_by = NULL;
    122175        frw->writers = 0;
    123176        frw->readers = 0;
     
    127180void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
    128181{
     182        fibril_t *f = (fibril_t *) fibril_get_id();
     183       
    129184        futex_down(&async_futex);
    130185        if (frw->writers) {
    131                 fibril_t *f = (fibril_t *) fibril_get_id();
    132186                awaiter_t wdata;
    133187
     
    138192                f->flags &= ~FIBRIL_WRITER;
    139193                list_append(&wdata.wu_event.link, &frw->waiters);
     194                check_for_deadlock(&frw->oi);
     195                f->waits_for = &frw->oi;
    140196                fibril_switch(FIBRIL_TO_MANAGER);
    141197        } else {
    142                 frw->readers++;
     198                /* Consider the first reader the owner. */
     199                if (frw->readers++ == 0)
     200                        frw->oi.owned_by = f;
    143201                futex_up(&async_futex);
    144202        }
     
    147205void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
    148206{
     207        fibril_t *f = (fibril_t *) fibril_get_id();
     208       
    149209        futex_down(&async_futex);
    150210        if (frw->writers || frw->readers) {
    151                 fibril_t *f = (fibril_t *) fibril_get_id();
    152211                awaiter_t wdata;
    153212
     
    158217                f->flags |= FIBRIL_WRITER;
    159218                list_append(&wdata.wu_event.link, &frw->waiters);
     219                check_for_deadlock(&frw->oi);
     220                f->waits_for = &frw->oi;
    160221                fibril_switch(FIBRIL_TO_MANAGER);
    161222        } else {
     223                frw->oi.owned_by = f;
    162224                frw->writers++;
    163225                futex_up(&async_futex);
     
    170232        assert(frw->readers || (frw->writers == 1));
    171233        if (frw->readers) {
    172                 if (--frw->readers)
     234                if (--frw->readers) {
     235                        if (frw->oi.owned_by == (fibril_t *) fibril_get_id()) {
     236                                /*
     237                                 * If this reader firbril was considered the
     238                                 * owner of this rwlock, clear the ownership
     239                                 * information even if there are still more
     240                                 * readers.
     241                                 *
     242                                 * This is the limitation of the detection
     243                                 * mechanism rooted in the fact that tracking
     244                                 * all readers would require dynamically
     245                                 * allocated memory for keeping linkage info.
     246                                 */
     247                                frw->oi.owned_by = NULL;
     248                        }
    173249                        goto out;
     250                }
    174251        } else {
    175252                frw->writers--;
     
    177254       
    178255        assert(!frw->readers && !frw->writers);
     256       
     257        frw->oi.owned_by = NULL;
    179258       
    180259        while (!list_empty(&frw->waiters)) {
     
    185264                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
    186265                f = (fibril_t *) wdp->fid;
     266               
     267                f->waits_for = NULL;
    187268               
    188269                if (f->flags & FIBRIL_WRITER) {
     
    194275                        fibril_add_ready(wdp->fid);
    195276                        frw->writers++;
     277                        frw->oi.owned_by = f;
    196278                        optimize_execution_power();
    197279                        break;
     
    201283                        list_remove(&wdp->wu_event.link);
    202284                        fibril_add_ready(wdp->fid);
    203                         frw->readers++;
     285                        if (frw->readers++ == 0) {
     286                                /* Consider the first reader the owner. */
     287                                frw->oi.owned_by = f;
     288                        }
    204289                        optimize_execution_power();
    205290                }
Note: See TracChangeset for help on using the changeset viewer.