Changeset 89c57b6 in mainline for uspace/lib/c/generic/fibril_synch.c


Ignore:
Timestamp:
2011-04-13T14:45:41Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
88634420
Parents:
cefb126 (diff), 17279ead (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    rcefb126 r89c57b6  
    3636#include <fibril.h>
    3737#include <async.h>
    38 #include <async_priv.h>
    3938#include <adt/list.h>
    4039#include <futex.h>
     
    4241#include <errno.h>
    4342#include <assert.h>
     43#include <stacktrace.h>
     44#include <stdlib.h>
     45#include "private/async.h"
    4446
    4547static void optimize_execution_power(void)
     
    5355         */
    5456        if (atomic_get(&threads_in_ipc_wait) > 0)
    55                 ipc_poke();
    56 }
     57                async_poke();
     58}
     59
     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
    5794
    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
     106        if (fibril_get_sercount() != 0)
     107                abort();
     108
    66109        futex_down(&async_futex);
    67110        if (fm->counter-- <= 0) {
     
    73116                link_initialize(&wdata.wu_event.link);
    74117                list_append(&wdata.wu_event.link, &fm->waiters);
     118                check_for_deadlock(&fm->oi);
     119                f->waits_for = &fm->oi;
    75120                fibril_switch(FIBRIL_TO_MANAGER);
    76121        } else {
     122                fm->oi.owned_by = f;
    77123                futex_up(&async_futex);
    78124        }
     
    86132        if (fm->counter > 0) {
    87133                fm->counter--;
     134                fm->oi.owned_by = (fibril_t *) fibril_get_id();
    88135                locked = true;
    89136        }
     
    95142static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm)
    96143{
    97         assert(fm->counter <= 0);
    98144        if (fm->counter++ < 0) {
    99145                link_t *tmp;
    100146                awaiter_t *wdp;
     147                fibril_t *f;
    101148       
    102149                assert(!list_empty(&fm->waiters));
     
    105152                wdp->active = true;
    106153                wdp->wu_event.inlist = false;
     154
     155                f = (fibril_t *) wdp->fid;
     156                fm->oi.owned_by = f;
     157                f->waits_for = NULL;
     158
    107159                list_remove(&wdp->wu_event.link);
    108160                fibril_add_ready(wdp->fid);
    109161                optimize_execution_power();
     162        } else {
     163                fm->oi.owned_by = NULL;
    110164        }
    111165}
     
    113167void fibril_mutex_unlock(fibril_mutex_t *fm)
    114168{
     169        assert(fibril_mutex_is_locked(fm));
    115170        futex_down(&async_futex);
    116171        _fibril_mutex_unlock_unsafe(fm);
     
    118173}
    119174
     175bool fibril_mutex_is_locked(fibril_mutex_t *fm)
     176{
     177        bool locked = false;
     178       
     179        futex_down(&async_futex);
     180        if (fm->counter <= 0)
     181                locked = true;
     182        futex_up(&async_futex);
     183       
     184        return locked;
     185}
     186
    120187void fibril_rwlock_initialize(fibril_rwlock_t *frw)
    121188{
     189        frw->oi.owned_by = NULL;
    122190        frw->writers = 0;
    123191        frw->readers = 0;
     
    127195void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
    128196{
     197        fibril_t *f = (fibril_t *) fibril_get_id();
     198       
     199        if (fibril_get_sercount() != 0)
     200                abort();
     201
    129202        futex_down(&async_futex);
    130203        if (frw->writers) {
    131                 fibril_t *f = (fibril_t *) fibril_get_id();
    132204                awaiter_t wdata;
    133205
     
    138210                f->flags &= ~FIBRIL_WRITER;
    139211                list_append(&wdata.wu_event.link, &frw->waiters);
     212                check_for_deadlock(&frw->oi);
     213                f->waits_for = &frw->oi;
    140214                fibril_switch(FIBRIL_TO_MANAGER);
    141215        } else {
    142                 frw->readers++;
     216                /* Consider the first reader the owner. */
     217                if (frw->readers++ == 0)
     218                        frw->oi.owned_by = f;
    143219                futex_up(&async_futex);
    144220        }
     
    147223void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
    148224{
     225        fibril_t *f = (fibril_t *) fibril_get_id();
     226       
     227        if (fibril_get_sercount() != 0)
     228                abort();
     229
    149230        futex_down(&async_futex);
    150231        if (frw->writers || frw->readers) {
    151                 fibril_t *f = (fibril_t *) fibril_get_id();
    152232                awaiter_t wdata;
    153233
     
    158238                f->flags |= FIBRIL_WRITER;
    159239                list_append(&wdata.wu_event.link, &frw->waiters);
     240                check_for_deadlock(&frw->oi);
     241                f->waits_for = &frw->oi;
    160242                fibril_switch(FIBRIL_TO_MANAGER);
    161243        } else {
     244                frw->oi.owned_by = f;
    162245                frw->writers++;
    163246                futex_up(&async_futex);
     
    168251{
    169252        futex_down(&async_futex);
    170         assert(frw->readers || (frw->writers == 1));
    171253        if (frw->readers) {
    172                 if (--frw->readers)
     254                if (--frw->readers) {
     255                        if (frw->oi.owned_by == (fibril_t *) fibril_get_id()) {
     256                                /*
     257                                 * If this reader firbril was considered the
     258                                 * owner of this rwlock, clear the ownership
     259                                 * information even if there are still more
     260                                 * readers.
     261                                 *
     262                                 * This is the limitation of the detection
     263                                 * mechanism rooted in the fact that tracking
     264                                 * all readers would require dynamically
     265                                 * allocated memory for keeping linkage info.
     266                                 */
     267                                frw->oi.owned_by = NULL;
     268                        }
    173269                        goto out;
     270                }
    174271        } else {
    175272                frw->writers--;
     
    177274       
    178275        assert(!frw->readers && !frw->writers);
     276       
     277        frw->oi.owned_by = NULL;
    179278       
    180279        while (!list_empty(&frw->waiters)) {
     
    185284                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
    186285                f = (fibril_t *) wdp->fid;
     286               
     287                f->waits_for = NULL;
    187288               
    188289                if (f->flags & FIBRIL_WRITER) {
     
    194295                        fibril_add_ready(wdp->fid);
    195296                        frw->writers++;
     297                        frw->oi.owned_by = f;
    196298                        optimize_execution_power();
    197299                        break;
     
    201303                        list_remove(&wdp->wu_event.link);
    202304                        fibril_add_ready(wdp->fid);
    203                         frw->readers++;
     305                        if (frw->readers++ == 0) {
     306                                /* Consider the first reader the owner. */
     307                                frw->oi.owned_by = f;
     308                        }
    204309                        optimize_execution_power();
    205310                }
     
    211316void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
    212317{
     318        assert(fibril_rwlock_is_read_locked(frw));
    213319        _fibril_rwlock_common_unlock(frw);
    214320}
     
    216322void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
    217323{
     324        assert(fibril_rwlock_is_write_locked(frw));
    218325        _fibril_rwlock_common_unlock(frw);
     326}
     327
     328bool fibril_rwlock_is_read_locked(fibril_rwlock_t *frw)
     329{
     330        bool locked = false;
     331
     332        futex_down(&async_futex);
     333        if (frw->readers)
     334                locked = true;
     335        futex_up(&async_futex);
     336
     337        return locked;
     338}
     339
     340bool fibril_rwlock_is_write_locked(fibril_rwlock_t *frw)
     341{
     342        bool locked = false;
     343
     344        futex_down(&async_futex);
     345        if (frw->writers) {
     346                assert(frw->writers == 1);
     347                locked = true;
     348        }
     349        futex_up(&async_futex);
     350
     351        return locked;
     352}
     353
     354bool fibril_rwlock_is_locked(fibril_rwlock_t *frw)
     355{
     356        return fibril_rwlock_is_read_locked(frw) ||
     357            fibril_rwlock_is_write_locked(frw);
    219358}
    220359
     
    229368{
    230369        awaiter_t wdata;
     370
     371        assert(fibril_mutex_is_locked(fm));
    231372
    232373        if (timeout < 0)
Note: See TracChangeset for help on using the changeset viewer.