summaryrefslogtreecommitdiffstats
path: root/testsuites/smptests/smpmrsp01/init.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-10 21:30:26 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-11 08:58:40 +0200
commitbe0366bb62ed4a804725a484ffd73242cd4f1d7b (patch)
tree4267cd07e8e1134284ec145280f8197480aa55b7 /testsuites/smptests/smpmrsp01/init.c
parentmrm332-testsuite.tcfg: Add fileio (diff)
downloadrtems-be0366bb62ed4a804725a484ffd73242cd4f1d7b.tar.bz2
score: Fix scheduler helping protocol
Account for priority changes of threads executing in a foreign partition. Exchange idle threads in case a victim node uses an idle thread and the new scheduled node needs an idle thread.
Diffstat (limited to 'testsuites/smptests/smpmrsp01/init.c')
-rw-r--r--testsuites/smptests/smpmrsp01/init.c224
1 files changed, 222 insertions, 2 deletions
diff --git a/testsuites/smptests/smpmrsp01/init.c b/testsuites/smptests/smpmrsp01/init.c
index a1aae86276..1f079047d5 100644
--- a/testsuites/smptests/smpmrsp01/init.c
+++ b/testsuites/smptests/smpmrsp01/init.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2014-2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -74,7 +74,6 @@ typedef struct {
} test_context;
static test_context test_instance = {
- .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
.switch_lock = SMP_LOCK_INITIALIZER("test instance switch lock")
};
@@ -87,6 +86,11 @@ static void busy_wait(void)
}
}
+static void barrier_init(test_context *ctx)
+{
+ _SMP_barrier_Control_initialize(&ctx->barrier);
+}
+
static void barrier(test_context *ctx, SMP_barrier_State *bs)
{
_SMP_barrier_Wait(&ctx->barrier, bs, 2);
@@ -291,6 +295,7 @@ static void test_mrsp_obtain_and_release(test_context *ctx)
change_prio(RTEMS_SELF, 3);
+ barrier_init(ctx);
reset_switch_events(ctx);
ctx->high_run[0] = false;
@@ -467,6 +472,219 @@ static void test_mrsp_obtain_and_release(test_context *ctx)
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
}
+static void obtain_after_migration_worker(rtems_task_argument arg)
+{
+ test_context *ctx = &test_instance;
+ rtems_status_code sc;
+ SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
+
+ assert_prio(RTEMS_SELF, 3);
+
+ sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ /* Worker done (K) */
+ barrier(ctx, &barrier_state);
+
+ while (true) {
+ /* Wait for termination */
+ }
+}
+
+static void obtain_after_migration_high(rtems_task_argument arg)
+{
+ test_context *ctx = &test_instance;
+ rtems_status_code sc;
+ SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
+
+ assert_prio(RTEMS_SELF, 2);
+
+ sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ /* Obtain done (I) */
+ barrier(ctx, &barrier_state);
+
+ /* Ready to release (J) */
+ barrier(ctx, &barrier_state);
+
+ sc = rtems_semaphore_release(ctx->mrsp_ids[1]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_task_suspend(RTEMS_SELF);
+ rtems_test_assert(0);
+}
+
+static void test_mrsp_obtain_after_migration(test_context *ctx)
+{
+ rtems_status_code sc;
+ rtems_task_priority prio;
+ rtems_id scheduler_id;
+ SMP_barrier_State barrier_state;
+
+ puts("test MrsP obtain after migration");
+
+ change_prio(RTEMS_SELF, 3);
+
+ barrier_init(ctx);
+ reset_switch_events(ctx);
+
+ /* Create tasks */
+
+ sc = rtems_task_create(
+ rtems_build_name('H', 'I', 'G', '0'),
+ 2,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->high_task_id[0]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_create(
+ rtems_build_name('W', 'O', 'R', 'K'),
+ 3,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->worker_ids[0]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_set_scheduler(ctx->worker_ids[0], ctx->scheduler_ids[1]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ /* Create a MrsP semaphore objects */
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('M', 'R', 'S', 'P'),
+ 1,
+ RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
+ | RTEMS_BINARY_SEMAPHORE,
+ 3,
+ &ctx->mrsp_ids[0]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('M', 'R', 'S', 'P'),
+ 1,
+ RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
+ | RTEMS_BINARY_SEMAPHORE,
+ 2,
+ &ctx->mrsp_ids[1]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('M', 'R', 'S', 'P'),
+ 1,
+ RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
+ | RTEMS_BINARY_SEMAPHORE,
+ 1,
+ &ctx->mrsp_ids[2]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ prio = 4;
+ sc = rtems_semaphore_set_priority(
+ ctx->mrsp_ids[2],
+ ctx->scheduler_ids[1],
+ prio,
+ &prio
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+ rtems_test_assert(prio == 1);
+
+ /* Check executing task parameters */
+
+ sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_test_assert(ctx->scheduler_ids[0] == scheduler_id);
+
+ assert_prio(RTEMS_SELF, 3);
+
+ sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ assert_prio(RTEMS_SELF, 3);
+
+ /* Start other tasks */
+
+ sc = rtems_task_start(ctx->worker_ids[0], obtain_after_migration_worker, 0);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(ctx->high_task_id[0], obtain_after_migration_high, 0);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_test_assert(rtems_get_current_processor() == 1);
+
+ /* Obtain done (I) */
+ _SMP_barrier_State_initialize(&barrier_state);
+ barrier(ctx, &barrier_state);
+
+ sc = rtems_task_suspend(ctx->high_task_id[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_test_assert(rtems_get_current_processor() == 1);
+
+ /*
+ * Obtain second MrsP semaphore and ensure that we change the priority of our
+ * own scheduler node and not the one we are currently using.
+ */
+
+ sc = rtems_semaphore_obtain(ctx->mrsp_ids[2], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ assert_prio(RTEMS_SELF, 1);
+
+ rtems_test_assert(rtems_get_current_processor() == 1);
+
+ sc = rtems_semaphore_release(ctx->mrsp_ids[2]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_resume(ctx->high_task_id[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ /* Ready to release (J) */
+ barrier(ctx, &barrier_state);
+
+ rtems_test_assert(rtems_get_current_processor() == 1);
+
+ /* Prepare barrier for worker */
+ barrier_init(ctx);
+ _SMP_barrier_State_initialize(&barrier_state);
+
+ sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_test_assert(rtems_get_current_processor() == 0);
+
+ print_switch_events(ctx);
+
+ /* Worker done (K) */
+ barrier(ctx, &barrier_state);
+
+ sc = rtems_task_delete(ctx->worker_ids[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_delete(ctx->high_task_id[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_delete(ctx->mrsp_ids[1]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_delete(ctx->mrsp_ids[2]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
static void test_mrsp_flush_error(void)
{
rtems_status_code sc;
@@ -1034,6 +1252,7 @@ static void test_mrsp_various_block_and_unblock(test_context *ctx)
change_prio(RTEMS_SELF, 4);
+ barrier_init(ctx);
reset_switch_events(ctx);
ctx->low_run[0] = false;
@@ -1637,6 +1856,7 @@ static void Init(rtems_task_argument arg)
test_mrsp_deadlock_error(ctx);
test_mrsp_multiple_obtain();
test_mrsp_various_block_and_unblock(ctx);
+ test_mrsp_obtain_after_migration(ctx);
test_mrsp_obtain_and_sleep_and_release(ctx);
test_mrsp_obtain_and_release_with_help(ctx);
test_mrsp_obtain_and_release(ctx);