From 97a98f6cd767b3a68279890488c7b451788f84f4 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 14 Nov 2017 12:57:01 +0100 Subject: RWLOCK(9): Add reader/writer lock implementation --- testsuite/rwlock01/test_main.c | 308 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 275 insertions(+), 33 deletions(-) (limited to 'testsuite') diff --git a/testsuite/rwlock01/test_main.c b/testsuite/rwlock01/test_main.c index a0ae91b6..8f00f3e7 100644 --- a/testsuite/rwlock01/test_main.c +++ b/testsuite/rwlock01/test_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -67,8 +67,11 @@ typedef struct { struct rwlock rw; bool done; int rv; + bool done2; + int rv2; int timo; rtems_id worker_task; + rtems_id worker2_task; } test_context; static test_context test_instance; @@ -83,9 +86,8 @@ set_self_prio(rtems_task_priority prio) } static void -worker_task(rtems_task_argument arg) +worker(test_context *ctx, int *rv, bool *done) { - test_context *ctx = (test_context *) arg; struct rwlock *rw = &ctx->rw; while (true) { @@ -102,36 +104,52 @@ worker_task(rtems_task_argument arg) if ((events & EVENT_RLOCK) != 0) { rw_rlock(rw); - ctx->done = true; + *done = true; } if ((events & EVENT_WLOCK) != 0) { rw_wlock(rw); - ctx->done = true; + *done = true; } if ((events & EVENT_TRY_RLOCK) != 0) { - ctx->rv = rw_try_rlock(rw); - ctx->done = true; + *rv = rw_try_rlock(rw); + *done = true; } if ((events & EVENT_TRY_WLOCK) != 0) { - ctx->rv = rw_try_wlock(rw); - ctx->done = true; + *rv = rw_try_wlock(rw); + *done = true; } if ((events & EVENT_UNLOCK) != 0) { rw_unlock(rw); - ctx->done = true; + *done = true; } if ((events & EVENT_SLEEP) != 0) { - ctx->rv = rw_sleep(ctx, rw, 0, "worker", ctx->timo); - ctx->done = true; + *rv = rw_sleep(ctx, rw, 0, "worker", ctx->timo); + *done = true; } } } +static void +worker_task(rtems_task_argument arg) +{ + test_context *ctx = (test_context *) arg; + + worker(ctx, &ctx->rv, &ctx->done); +} + +static void +worker2_task(rtems_task_argument arg) +{ + test_context *ctx = (test_context *) arg; + + worker(ctx, &ctx->rv2, &ctx->done2); +} + static void send_events(test_context *ctx, rtems_event_set events) { @@ -141,13 +159,22 @@ send_events(test_context *ctx, rtems_event_set events) assert(sc == RTEMS_SUCCESSFUL); } +static void +send_events2(test_context *ctx, rtems_event_set events) +{ + rtems_status_code sc; + + sc = rtems_event_send(ctx->worker2_task, events); + assert(sc == RTEMS_SUCCESSFUL); +} + static void start_worker(test_context *ctx) { rtems_status_code sc; sc = rtems_task_create( - rtems_build_name('W', 'O', 'R', 'K'), + rtems_build_name('W', 'R', 'K', '1'), PRIO_WORKER, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, @@ -162,6 +189,23 @@ start_worker(test_context *ctx) (rtems_task_argument) ctx ); assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('W', 'R', 'K', '2'), + PRIO_WORKER, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &ctx->worker2_task + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start( + ctx->worker2_task, + worker2_task, + (rtems_task_argument) ctx + ); + assert(sc == RTEMS_SUCCESSFUL); } static void @@ -171,6 +215,9 @@ delete_worker(test_context *ctx) sc = rtems_task_delete(ctx->worker_task); assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_delete(ctx->worker2_task); + assert(sc == RTEMS_SUCCESSFUL); } static void @@ -186,13 +233,17 @@ test_rw_non_recursive(test_context *ctx) assert(rw_initialized(rw)); rw_rlock(rw); - /* FIXME: We use a mutex implementation */ - assert(rw_wowned(rw)); + assert(!rw_wowned(rw)); rw_runlock(rw); rw_rlock(rw); rw_unlock(rw); + rw_rlock(rw); + rw_rlock(rw); + rw_runlock(rw); + rw_runlock(rw); + rw_rlock(rw); ok = rw_try_upgrade(rw); assert(ok != 0); @@ -210,8 +261,7 @@ test_rw_non_recursive(test_context *ctx) assert(ok != 0); assert(rw_wowned(rw)); rw_downgrade(rw); - /* FIXME: We use a mutex implementation */ - assert(rw_wowned(rw)); + assert(!rw_wowned(rw)); rw_runlock(rw); rw_rlock(rw); @@ -219,8 +269,7 @@ test_rw_non_recursive(test_context *ctx) assert(ok != 0); assert(rw_wowned(rw)); rw_downgrade(rw); - /* FIXME: We use a mutex implementation */ - assert(rw_wowned(rw)); + assert(!rw_wowned(rw)); rw_unlock(rw); rw_wlock(rw); @@ -252,11 +301,6 @@ test_rw_recursive(test_context *ctx) rw_init_flags(rw, "test", RW_RECURSE); assert(rw_initialized(rw)); - rw_rlock(rw); - rw_rlock(rw); - rw_runlock(rw); - rw_runlock(rw); - rw_wlock(rw); rw_wlock(rw); rw_wunlock(rw); @@ -275,13 +319,15 @@ test_rw_try_rlock(test_context *ctx) rw_init(rw, "test"); rw_rlock(rw); - /* FIXME: We use a mutex implementation */ ctx->done = false; - ctx->rv = 1; + ctx->rv = 0; send_events(ctx, EVENT_TRY_RLOCK); assert(ctx->done); - assert(ctx->rv == 0); + assert(ctx->rv == 1); rw_unlock(rw); + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); rw_wlock(rw); ctx->done = false; @@ -332,10 +378,9 @@ test_rw_rlock(test_context *ctx) rw_init(rw, "test"); rw_rlock(rw); - /* FIXME: We use a mutex implementation */ ctx->done = false; send_events(ctx, EVENT_RLOCK); - assert(!ctx->done); + assert(ctx->done); rw_unlock(rw); assert(ctx->done); ctx->done = false; @@ -387,6 +432,202 @@ test_rw_wlock(test_context *ctx) rw_destroy(rw); } +static void +test_rw_rlock_phase_fair(test_context *ctx) +{ + struct rwlock *rw = &ctx->rw; + + puts("test rw rlock phase fair"); + + rw_init(rw, "test"); + + rw_rlock(rw); + + ctx->done = false; + send_events(ctx, EVENT_WLOCK); + assert(!ctx->done); + + ctx->done2 = false; + send_events2(ctx, EVENT_RLOCK); + assert(!ctx->done2); + + rw_unlock(rw); + assert(ctx->done); + assert(!ctx->done2); + + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); + assert(ctx->done2); + + ctx->done2 = false; + send_events2(ctx, EVENT_UNLOCK); + assert(ctx->done2); + + rw_destroy(rw); +} + +static void +test_rw_wlock_phase_fair(test_context *ctx) +{ + struct rwlock *rw = &ctx->rw; + + puts("test rw wlock phase fair"); + + rw_init(rw, "test"); + + rw_wlock(rw); + + ctx->done = false; + send_events(ctx, EVENT_WLOCK); + assert(!ctx->done); + + ctx->done2 = false; + send_events2(ctx, EVENT_RLOCK); + assert(!ctx->done2); + + rw_unlock(rw); + assert(!ctx->done); + assert(ctx->done2); + + ctx->done2 = false; + send_events2(ctx, EVENT_UNLOCK); + assert(ctx->done2); + assert(ctx->done); + + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); + + rw_destroy(rw); +} + +static void +test_rw_try_upgrade(test_context *ctx) +{ + struct rwlock *rw = &ctx->rw; + int ok; + + puts("test rw try upgrade"); + + rw_init(rw, "test"); + + rw_rlock(rw); + + ctx->done = false; + send_events(ctx, EVENT_WLOCK); + assert(!ctx->done); + + assert(!rw_wowned(rw)); + ok = rw_try_upgrade(rw); + assert(ok != 0); + assert(rw_wowned(rw)); + assert(!ctx->done); + + rw_unlock(rw); + assert(!rw_wowned(rw)); + assert(ctx->done); + + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); + + rw_rlock(rw); + + ctx->done = false; + send_events(ctx, EVENT_WLOCK); + assert(!ctx->done); + + ctx->done2 = false; + send_events2(ctx, EVENT_RLOCK); + assert(!ctx->done2); + + assert(!rw_wowned(rw)); + ok = rw_try_upgrade(rw); + assert(ok != 0); + assert(rw_wowned(rw)); + assert(!ctx->done); + assert(!ctx->done2); + + rw_unlock(rw); + assert(!rw_wowned(rw)); + assert(!ctx->done); + assert(ctx->done2); + + ctx->done2 = false; + send_events2(ctx, EVENT_UNLOCK); + assert(ctx->done2); + assert(ctx->done); + + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); + + rw_rlock(rw); + + ctx->done = false; + send_events(ctx, EVENT_RLOCK); + assert(ctx->done); + + assert(!rw_wowned(rw)); + ok = rw_try_upgrade(rw); + assert(ok == 0); + assert(!rw_wowned(rw)); + + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); + + assert(!rw_wowned(rw)); + ok = rw_try_upgrade(rw); + assert(ok != 0); + assert(rw_wowned(rw)); + + rw_unlock(rw); + assert(!rw_wowned(rw)); + + rw_destroy(rw); +} + +static void +test_rw_downgrade(test_context *ctx) +{ + struct rwlock *rw = &ctx->rw; + + puts("test rw downgrade"); + + rw_init(rw, "test"); + + rw_wlock(rw); + assert(rw_wowned(rw)); + + rw_downgrade(rw); + assert(!rw_wowned(rw)); + + rw_unlock(rw); + assert(!rw_wowned(rw)); + + rw_wlock(rw); + assert(rw_wowned(rw)); + + ctx->done = false; + send_events(ctx, EVENT_RLOCK); + assert(!ctx->done); + + rw_downgrade(rw); + assert(!rw_wowned(rw)); + assert(ctx->done); + + rw_unlock(rw); + assert(!rw_wowned(rw)); + + ctx->done = false; + send_events(ctx, EVENT_UNLOCK); + assert(ctx->done); + + rw_destroy(rw); +} + static void test_rw_sleep_with_rlock(test_context *ctx) { @@ -407,11 +648,8 @@ test_rw_sleep_with_rlock(test_context *ctx) rw_rlock(rw); wakeup(ctx); - /* FIXME: We use a mutex implementation */ - assert(!ctx->done); - rw_unlock(rw); - /* FIXME: We use a mutex implementation */ assert(ctx->done); + rw_unlock(rw); ctx->done = false; send_events(ctx, EVENT_UNLOCK); @@ -511,6 +749,10 @@ test_main(void) test_rw_try_wlock(ctx); test_rw_rlock(ctx); test_rw_wlock(ctx); + test_rw_rlock_phase_fair(ctx); + test_rw_wlock_phase_fair(ctx); + test_rw_try_upgrade(ctx); + test_rw_downgrade(ctx); assert(rtems_resource_snapshot_check(&snapshot_1)); -- cgit v1.2.3