Changeset 97a98f6 in rtems-libbsd


Ignore:
Timestamp:
Nov 14, 2017, 11:57:01 AM (19 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
eeb3fd5d9b07ac9a2e280cff60a1b762bd273a8d, 1e989998de954bef51e6c19cc3d64d39f32100aa
Children:
cc7a8d8
Parents:
344b8e6
git-author:
Sebastian Huber <sebastian.huber@…> (11/14/17 11:57:01)
git-committer:
Sebastian Huber <sebastian.huber@…> (11/16/17 08:02:24)
Message:

RWLOCK(9): Add reader/writer lock implementation

Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • freebsd/sys/sys/_rwlock.h

    r344b8e6 r97a98f6  
    3030#define _SYS__RWLOCK_H_
    3131#ifdef __rtems__
    32 #include <machine/rtems-bsd-mutex.h>
     32#include <machine/rtems-bsd-rwlock.h>
    3333#endif /* __rtems__ */
    3434
     
    4949        volatile uintptr_t      rw_lock;
    5050#else /* __rtems__ */
    51         rtems_bsd_mutex mutex;
     51        rtems_bsd_rwlock        rwlock;
    5252#endif /* __rtems__ */
    5353};
  • libbsd.py

    r344b8e6 r97a98f6  
    111111            'rtems/rtems-kernel-program.c',
    112112            'rtems/rtems-kernel-rwlock.c',
     113            'rtems/rtems-kernel-rwlockimpl.c',
    113114            'rtems/rtems-kernel-signal.c',
    114115            'rtems/rtems-kernel-sx.c',
  • libbsd_waf.py

    r344b8e6 r97a98f6  
    23592359              'rtemsbsd/rtems/rtems-kernel-program.c',
    23602360              'rtemsbsd/rtems/rtems-kernel-rwlock.c',
     2361              'rtemsbsd/rtems/rtems-kernel-rwlockimpl.c',
    23612362              'rtemsbsd/rtems/rtems-kernel-signal.c',
    23622363              'rtemsbsd/rtems/rtems-kernel-sx.c',
  • rtemsbsd/rtems/rtems-kernel-rwlock.c

    r344b8e6 r97a98f6  
    1616 *  <kevin.kirspel@optimedical.com>
    1717 *
    18  * Copyright (c) 2013-2015 embedded brains GmbH.  All rights reserved.
     18 * Copyright (c) 2013, 2017 embedded brains GmbH.  All rights reserved.
    1919 *
    2020 *  embedded brains GmbH
     
    2323 *  Germany
    2424 *  <rtems@embedded-brains.de>
     25 *
     26 * Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
     27 * All rights reserved.
    2528 *
    2629 * Redistribution and use in source and binary forms, with or without
     
    4750
    4851#include <machine/rtems-bsd-kernel-space.h>
    49 #include <machine/rtems-bsd-muteximpl.h>
     52#include <machine/rtems-bsd-rwlockimpl.h>
    5053
    5154#include <sys/param.h>
     
    7174};
    7275
    73 #define rw_wowner(rw) rtems_bsd_mutex_owner(&(rw)->mutex)
    74 
    75 #define rw_recursed(rw) rtems_bsd_mutex_recursed(&(rw)->mutex)
     76#define rw_wowner(rw) rtems_bsd_rwlock_wowner(&(rw)->rwlock)
     77
     78#define rw_recursed(rw) rtems_bsd_rwlock_recursed(&(rw)->rwlock)
    7679
    7780void
     
    8588lock_rw(struct lock_object *lock, uintptr_t how)
    8689{
    87 
    88         rw_wlock((struct rwlock *)lock);
     90        struct rwlock *rw;
     91
     92        rw = (struct rwlock *)lock;
     93        if (how)
     94                rw_rlock(rw);
     95        else
     96                rw_wlock(rw);
    8997}
    9098
     
    92100unlock_rw(struct lock_object *lock)
    93101{
    94 
    95         rw_unlock((struct rwlock *)lock);
    96         return (0);
     102        struct rwlock *rw;
     103
     104        rw = (struct rwlock *)lock;
     105        rw_assert(rw, RA_LOCKED | LA_NOTRECURSED);
     106        if (rw->rwlock.readers > 0) {
     107                rw_runlock(rw);
     108                return (1);
     109        } else {
     110                rw_wunlock(rw);
     111                return (0);
     112        }
    97113}
    98114
     
    106122                flags |= LO_RECURSABLE;
    107123
    108         rtems_bsd_mutex_init(&rw->lock_object, &rw->mutex, &lock_class_rw,
     124        rtems_bsd_rwlock_init(&rw->lock_object, &rw->rwlock, &lock_class_rw,
    109125            name, NULL, flags);
    110126}
     
    114130{
    115131
    116         rtems_bsd_mutex_destroy(&rw->lock_object, &rw->mutex);
     132        rtems_bsd_rwlock_destroy(&rw->lock_object, &rw->rwlock);
    117133}
    118134
     
    120136rw_sysinit(void *arg)
    121137{
    122   struct rw_args *args = arg;
    123 
    124   rw_init(args->ra_rw, args->ra_desc);
     138        struct rw_args *args = arg;
     139
     140        rw_init((struct rwlock *)args->ra_rw, args->ra_desc);
    125141}
    126142
     
    128144rw_sysinit_flags(void *arg)
    129145{
    130   struct rw_args_flags *args = arg;
    131 
    132   rw_init_flags(args->ra_rw, args->ra_desc, args->ra_flags);
     146        struct rw_args_flags *args = arg;
     147
     148        rw_init_flags((struct rwlock *)args->ra_rw, args->ra_desc,
     149            args->ra_flags);
    133150}
    134151
     
    136153rw_wowned(struct rwlock *rw)
    137154{
    138         return (rtems_bsd_mutex_owned(&rw->mutex));
     155
     156        return (rtems_bsd_rwlock_wowned(&rw->rwlock));
    139157}
    140158
     
    142160_rw_wlock(struct rwlock *rw, const char *file, int line)
    143161{
    144         rtems_bsd_mutex_lock(&rw->lock_object, &rw->mutex);
     162
     163        rtems_bsd_rwlock_wlock(&rw->lock_object, &rw->rwlock);
    145164}
    146165
     
    148167_rw_try_wlock(struct rwlock *rw, const char *file, int line)
    149168{
    150         return (rtems_bsd_mutex_trylock(&rw->lock_object, &rw->mutex));
     169
     170        return (rtems_bsd_rwlock_try_wlock(&rw->lock_object, &rw->rwlock));
    151171}
    152172
     
    154174_rw_wunlock(struct rwlock *rw, const char *file, int line)
    155175{
    156         rtems_bsd_mutex_unlock(&rw->mutex);
     176
     177        rtems_bsd_rwlock_wunlock(&rw->rwlock);
    157178}
    158179
     
    160181_rw_rlock(struct rwlock *rw, const char *file, int line)
    161182{
    162         rtems_bsd_mutex_lock(&rw->lock_object, &rw->mutex);
     183
     184        rtems_bsd_rwlock_rlock(&rw->lock_object, &rw->rwlock);
    163185}
    164186
     
    166188_rw_try_rlock(struct rwlock *rw, const char *file, int line)
    167189{
    168         return (rtems_bsd_mutex_trylock(&rw->lock_object, &rw->mutex));
     190
     191        return (rtems_bsd_rwlock_try_rlock(&rw->lock_object, &rw->rwlock));
    169192}
    170193
     
    172195_rw_runlock(struct rwlock *rw, const char *file, int line)
    173196{
    174         rtems_bsd_mutex_unlock(&rw->mutex);
     197
     198        rtems_bsd_rwlock_runlock(&rw->rwlock);
    175199}
    176200
     
    178202_rw_try_upgrade(struct rwlock *rw, const char *file, int line)
    179203{
    180         return (1);
     204
     205        return (rtems_bsd_rwlock_try_upgrade(&rw->rwlock));
    181206}
    182207
     
    184209_rw_downgrade(struct rwlock *rw, const char *file, int line)
    185210{
    186         /* Nothing to do */
     211
     212        rtems_bsd_rwlock_downgrade(&rw->rwlock);
    187213}
    188214
     
    196222_rw_assert(const struct rwlock *rw, int what, const char *file, int line)
    197223{
    198         const char *name = rtems_bsd_mutex_name(&rw->mutex);
     224        const char *name = rtems_bsd_rwlock_name(&rw->rwlock);
    199225
    200226        switch (what) {
     
    205231        case RA_RLOCKED | RA_RECURSED:
    206232        case RA_RLOCKED | RA_NOTRECURSED:
     233#ifdef WITNESS
     234                witness_assert(&rw->lock_object, what, file, line);
     235#else
     236                /*
     237                 * If some other thread has a write lock or we have one
     238                 * and are asserting a read lock, fail.  Also, if no one
     239                 * has a lock at all, fail.
     240                 */
     241                if ((rw->rwlock.readers == 0 && rw_wowner(rw) == NULL) ||
     242                    (rw->rwlock.readers == 0 && (what & RA_RLOCKED ||
     243                    rw_wowner(rw) != _Thread_Get_executing())))
     244                        panic("Lock %s not %slocked @ %s:%d\n",
     245                            name, (what & RA_RLOCKED) ?
     246                            "read " : "", file, line);
     247
     248                if (rw->rwlock.readers == 0 && !(what & RA_RLOCKED)) {
     249                        if (rw_recursed(rw)) {
     250                                if (what & RA_NOTRECURSED)
     251                                        panic("Lock %s recursed @ %s:%d\n",
     252                                            name, file,
     253                                            line);
     254                        } else if (what & RA_RECURSED)
     255                                panic("Lock %s not recursed @ %s:%d\n",
     256                                    name, file, line);
     257                }
     258#endif
     259                break;
    207260        case RA_WLOCKED:
    208261        case RA_WLOCKED | RA_RECURSED:
     
    213266                if (rw_recursed(rw)) {
    214267                        if (what & RA_NOTRECURSED)
    215                                 panic("Lock %s recursed @ %s:%d\n", name, file,
    216                                     line);
     268                                panic("Lock %s recursed @ %s:%d\n",
     269                                    name, file, line);
    217270                } else if (what & RA_RECURSED)
    218                         panic("Lock %s not recursed @ %s:%d\n", name, file,
    219                             line);
     271                        panic("Lock %s not recursed @ %s:%d\n",
     272                            name, file, line);
    220273                break;
    221274        case RA_UNLOCKED:
     
    228281                 */
    229282                if (rw_wowner(rw) == _Thread_Get_executing())
    230                         panic("Lock %s exclusively locked @ %s:%d\n", name,
    231                             file, line);
     283                        panic("Lock %s exclusively locked @ %s:%d\n",
     284                            name, file, line);
    232285#endif
    233286                break;
  • testsuite/rwlock01/test_main.c

    r344b8e6 r97a98f6  
    11/*
    2  * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2013, 2017 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    6868        bool done;
    6969        int rv;
     70        bool done2;
     71        int rv2;
    7072        int timo;
    7173        rtems_id worker_task;
     74        rtems_id worker2_task;
    7275} test_context;
    7376
     
    8487
    8588static void
    86 worker_task(rtems_task_argument arg)
    87 {
    88         test_context *ctx = (test_context *) arg;
     89worker(test_context *ctx, int *rv, bool *done)
     90{
    8991        struct rwlock *rw = &ctx->rw;
    9092
     
    103105                if ((events & EVENT_RLOCK) != 0) {
    104106                        rw_rlock(rw);
    105                         ctx->done = true;
     107                        *done = true;
    106108                }
    107109
    108110                if ((events & EVENT_WLOCK) != 0) {
    109111                        rw_wlock(rw);
    110                         ctx->done = true;
     112                        *done = true;
    111113                }
    112114
    113115                if ((events & EVENT_TRY_RLOCK) != 0) {
    114                         ctx->rv = rw_try_rlock(rw);
    115                         ctx->done = true;
     116                        *rv = rw_try_rlock(rw);
     117                        *done = true;
    116118                }
    117119
    118120                if ((events & EVENT_TRY_WLOCK) != 0) {
    119                         ctx->rv = rw_try_wlock(rw);
    120                         ctx->done = true;
     121                        *rv = rw_try_wlock(rw);
     122                        *done = true;
    121123                }
    122124
    123125                if ((events & EVENT_UNLOCK) != 0) {
    124126                        rw_unlock(rw);
    125                         ctx->done = true;
     127                        *done = true;
    126128                }
    127129
    128130                if ((events & EVENT_SLEEP) != 0) {
    129                         ctx->rv = rw_sleep(ctx, rw, 0, "worker", ctx->timo);
    130                         ctx->done = true;
     131                        *rv = rw_sleep(ctx, rw, 0, "worker", ctx->timo);
     132                        *done = true;
    131133                }
    132134        }
     
    134136
    135137static void
     138worker_task(rtems_task_argument arg)
     139{
     140        test_context *ctx = (test_context *) arg;
     141
     142        worker(ctx, &ctx->rv, &ctx->done);
     143}
     144
     145static void
     146worker2_task(rtems_task_argument arg)
     147{
     148        test_context *ctx = (test_context *) arg;
     149
     150        worker(ctx, &ctx->rv2, &ctx->done2);
     151}
     152
     153static void
    136154send_events(test_context *ctx, rtems_event_set events)
    137155{
     
    143161
    144162static void
     163send_events2(test_context *ctx, rtems_event_set events)
     164{
     165        rtems_status_code sc;
     166
     167        sc = rtems_event_send(ctx->worker2_task, events);
     168        assert(sc == RTEMS_SUCCESSFUL);
     169}
     170
     171static void
    145172start_worker(test_context *ctx)
    146173{
     
    148175
    149176        sc = rtems_task_create(
    150                 rtems_build_name('W', 'O', 'R', 'K'),
     177                rtems_build_name('W', 'R', 'K', '1'),
    151178                PRIO_WORKER,
    152179                RTEMS_MINIMUM_STACK_SIZE,
     
    163190        );
    164191        assert(sc == RTEMS_SUCCESSFUL);
     192
     193        sc = rtems_task_create(
     194                rtems_build_name('W', 'R', 'K', '2'),
     195                PRIO_WORKER,
     196                RTEMS_MINIMUM_STACK_SIZE,
     197                RTEMS_DEFAULT_MODES,
     198                RTEMS_FLOATING_POINT,
     199                &ctx->worker2_task
     200        );
     201        assert(sc == RTEMS_SUCCESSFUL);
     202
     203        sc = rtems_task_start(
     204                ctx->worker2_task,
     205                worker2_task,
     206                (rtems_task_argument) ctx
     207        );
     208        assert(sc == RTEMS_SUCCESSFUL);
    165209}
    166210
     
    172216        sc = rtems_task_delete(ctx->worker_task);
    173217        assert(sc == RTEMS_SUCCESSFUL);
     218
     219        sc = rtems_task_delete(ctx->worker2_task);
     220        assert(sc == RTEMS_SUCCESSFUL);
    174221}
    175222
     
    187234
    188235        rw_rlock(rw);
    189         /* FIXME: We use a mutex implementation */
    190         assert(rw_wowned(rw));
     236        assert(!rw_wowned(rw));
    191237        rw_runlock(rw);
    192238
     
    195241
    196242        rw_rlock(rw);
     243        rw_rlock(rw);
     244        rw_runlock(rw);
     245        rw_runlock(rw);
     246
     247        rw_rlock(rw);
    197248        ok = rw_try_upgrade(rw);
    198249        assert(ok != 0);
     
    211262        assert(rw_wowned(rw));
    212263        rw_downgrade(rw);
    213         /* FIXME: We use a mutex implementation */
    214         assert(rw_wowned(rw));
     264        assert(!rw_wowned(rw));
    215265        rw_runlock(rw);
    216266
     
    220270        assert(rw_wowned(rw));
    221271        rw_downgrade(rw);
    222         /* FIXME: We use a mutex implementation */
    223         assert(rw_wowned(rw));
     272        assert(!rw_wowned(rw));
    224273        rw_unlock(rw);
    225274
     
    253302        assert(rw_initialized(rw));
    254303
    255         rw_rlock(rw);
    256         rw_rlock(rw);
    257         rw_runlock(rw);
    258         rw_runlock(rw);
    259 
    260304        rw_wlock(rw);
    261305        rw_wlock(rw);
     
    276320
    277321        rw_rlock(rw);
    278         /* FIXME: We use a mutex implementation */
     322        ctx->done = false;
     323        ctx->rv = 0;
     324        send_events(ctx, EVENT_TRY_RLOCK);
     325        assert(ctx->done);
     326        assert(ctx->rv == 1);
     327        rw_unlock(rw);
     328        ctx->done = false;
     329        send_events(ctx, EVENT_UNLOCK);
     330        assert(ctx->done);
     331
     332        rw_wlock(rw);
    279333        ctx->done = false;
    280334        ctx->rv = 1;
     
    284338        rw_unlock(rw);
    285339
    286         rw_wlock(rw);
    287         ctx->done = false;
    288         ctx->rv = 1;
    289         send_events(ctx, EVENT_TRY_RLOCK);
    290         assert(ctx->done);
    291         assert(ctx->rv == 0);
    292         rw_unlock(rw);
    293 
    294340        rw_destroy(rw);
    295341}
     
    333379
    334380        rw_rlock(rw);
    335         /* FIXME: We use a mutex implementation */
    336381        ctx->done = false;
    337382        send_events(ctx, EVENT_RLOCK);
    338         assert(!ctx->done);
     383        assert(ctx->done);
    339384        rw_unlock(rw);
    340385        assert(ctx->done);
     
    381426        rw_unlock(rw);
    382427        assert(ctx->done);
     428        ctx->done = false;
     429        send_events(ctx, EVENT_UNLOCK);
     430        assert(ctx->done);
     431
     432        rw_destroy(rw);
     433}
     434
     435static void
     436test_rw_rlock_phase_fair(test_context *ctx)
     437{
     438        struct rwlock *rw = &ctx->rw;
     439
     440        puts("test rw rlock phase fair");
     441
     442        rw_init(rw, "test");
     443
     444        rw_rlock(rw);
     445
     446        ctx->done = false;
     447        send_events(ctx, EVENT_WLOCK);
     448        assert(!ctx->done);
     449
     450        ctx->done2 = false;
     451        send_events2(ctx, EVENT_RLOCK);
     452        assert(!ctx->done2);
     453
     454        rw_unlock(rw);
     455        assert(ctx->done);
     456        assert(!ctx->done2);
     457
     458        ctx->done = false;
     459        send_events(ctx, EVENT_UNLOCK);
     460        assert(ctx->done);
     461        assert(ctx->done2);
     462
     463        ctx->done2 = false;
     464        send_events2(ctx, EVENT_UNLOCK);
     465        assert(ctx->done2);
     466
     467        rw_destroy(rw);
     468}
     469
     470static void
     471test_rw_wlock_phase_fair(test_context *ctx)
     472{
     473        struct rwlock *rw = &ctx->rw;
     474
     475        puts("test rw wlock phase fair");
     476
     477        rw_init(rw, "test");
     478
     479        rw_wlock(rw);
     480
     481        ctx->done = false;
     482        send_events(ctx, EVENT_WLOCK);
     483        assert(!ctx->done);
     484
     485        ctx->done2 = false;
     486        send_events2(ctx, EVENT_RLOCK);
     487        assert(!ctx->done2);
     488
     489        rw_unlock(rw);
     490        assert(!ctx->done);
     491        assert(ctx->done2);
     492
     493        ctx->done2 = false;
     494        send_events2(ctx, EVENT_UNLOCK);
     495        assert(ctx->done2);
     496        assert(ctx->done);
     497
     498        ctx->done = false;
     499        send_events(ctx, EVENT_UNLOCK);
     500        assert(ctx->done);
     501
     502        rw_destroy(rw);
     503}
     504
     505static void
     506test_rw_try_upgrade(test_context *ctx)
     507{
     508        struct rwlock *rw = &ctx->rw;
     509        int ok;
     510
     511        puts("test rw try upgrade");
     512
     513        rw_init(rw, "test");
     514
     515        rw_rlock(rw);
     516
     517        ctx->done = false;
     518        send_events(ctx, EVENT_WLOCK);
     519        assert(!ctx->done);
     520
     521        assert(!rw_wowned(rw));
     522        ok = rw_try_upgrade(rw);
     523        assert(ok != 0);
     524        assert(rw_wowned(rw));
     525        assert(!ctx->done);
     526
     527        rw_unlock(rw);
     528        assert(!rw_wowned(rw));
     529        assert(ctx->done);
     530
     531        ctx->done = false;
     532        send_events(ctx, EVENT_UNLOCK);
     533        assert(ctx->done);
     534
     535        rw_rlock(rw);
     536
     537        ctx->done = false;
     538        send_events(ctx, EVENT_WLOCK);
     539        assert(!ctx->done);
     540
     541        ctx->done2 = false;
     542        send_events2(ctx, EVENT_RLOCK);
     543        assert(!ctx->done2);
     544
     545        assert(!rw_wowned(rw));
     546        ok = rw_try_upgrade(rw);
     547        assert(ok != 0);
     548        assert(rw_wowned(rw));
     549        assert(!ctx->done);
     550        assert(!ctx->done2);
     551
     552        rw_unlock(rw);
     553        assert(!rw_wowned(rw));
     554        assert(!ctx->done);
     555        assert(ctx->done2);
     556
     557        ctx->done2 = false;
     558        send_events2(ctx, EVENT_UNLOCK);
     559        assert(ctx->done2);
     560        assert(ctx->done);
     561
     562        ctx->done = false;
     563        send_events(ctx, EVENT_UNLOCK);
     564        assert(ctx->done);
     565
     566        rw_rlock(rw);
     567
     568        ctx->done = false;
     569        send_events(ctx, EVENT_RLOCK);
     570        assert(ctx->done);
     571
     572        assert(!rw_wowned(rw));
     573        ok = rw_try_upgrade(rw);
     574        assert(ok == 0);
     575        assert(!rw_wowned(rw));
     576
     577        ctx->done = false;
     578        send_events(ctx, EVENT_UNLOCK);
     579        assert(ctx->done);
     580
     581        assert(!rw_wowned(rw));
     582        ok = rw_try_upgrade(rw);
     583        assert(ok != 0);
     584        assert(rw_wowned(rw));
     585
     586        rw_unlock(rw);
     587        assert(!rw_wowned(rw));
     588
     589        rw_destroy(rw);
     590}
     591
     592static void
     593test_rw_downgrade(test_context *ctx)
     594{
     595        struct rwlock *rw = &ctx->rw;
     596
     597        puts("test rw downgrade");
     598
     599        rw_init(rw, "test");
     600
     601        rw_wlock(rw);
     602        assert(rw_wowned(rw));
     603
     604        rw_downgrade(rw);
     605        assert(!rw_wowned(rw));
     606
     607        rw_unlock(rw);
     608        assert(!rw_wowned(rw));
     609
     610        rw_wlock(rw);
     611        assert(rw_wowned(rw));
     612
     613        ctx->done = false;
     614        send_events(ctx, EVENT_RLOCK);
     615        assert(!ctx->done);
     616
     617        rw_downgrade(rw);
     618        assert(!rw_wowned(rw));
     619        assert(ctx->done);
     620
     621        rw_unlock(rw);
     622        assert(!rw_wowned(rw));
     623
    383624        ctx->done = false;
    384625        send_events(ctx, EVENT_UNLOCK);
     
    408649        rw_rlock(rw);
    409650        wakeup(ctx);
    410         /* FIXME: We use a mutex implementation */
    411         assert(!ctx->done);
    412         rw_unlock(rw);
    413         /* FIXME: We use a mutex implementation */
    414         assert(ctx->done);
     651        assert(ctx->done);
     652        rw_unlock(rw);
    415653
    416654        ctx->done = false;
     
    512750        test_rw_rlock(ctx);
    513751        test_rw_wlock(ctx);
     752        test_rw_rlock_phase_fair(ctx);
     753        test_rw_wlock_phase_fair(ctx);
     754        test_rw_try_upgrade(ctx);
     755        test_rw_downgrade(ctx);
    514756
    515757        assert(rtems_resource_snapshot_check(&snapshot_1));
Note: See TracChangeset for help on using the changeset viewer.