[rtems commit] smptests/smpstrongapa01: Add test cases

Sebastian Huber sebh at rtems.org
Thu Jun 30 07:55:17 UTC 2016


Module:    rtems
Branch:    master
Commit:    4fe0e97f91fd14604c7644845c347f3c96472d3b
Changeset: http://git.rtems.org/rtems/commit/?id=4fe0e97f91fd14604c7644845c347f3c96472d3b

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Jun 30 09:50:41 2016 +0200

smptests/smpstrongapa01: Add test cases

---

 testsuites/smptests/smpstrongapa01/init.c | 303 +++++++++++++++++++++++++++++-
 1 file changed, 300 insertions(+), 3 deletions(-)

diff --git a/testsuites/smptests/smpstrongapa01/init.c b/testsuites/smptests/smpstrongapa01/init.c
index 5594d74..35b45a6 100644
--- a/testsuites/smptests/smpstrongapa01/init.c
+++ b/testsuites/smptests/smpstrongapa01/init.c
@@ -18,30 +18,327 @@
 
 #include "tmacros.h"
 
+#include <rtems/score/threadimpl.h>
+
 const char rtems_test_name[] = "SMPSTRONGAPA 1";
 
+#define CPU_COUNT 4
+
+#define TASK_COUNT (3 * CPU_COUNT)
+
+#define P(i) (UINT32_C(2) + i)
+
+#define ALL ((UINT32_C(1) << CPU_COUNT) - 1)
+
+#define IDLE UINT8_C(255)
+
+#define NAME rtems_build_name('S', 'A', 'P', 'A')
+
+typedef struct {
+  enum {
+    KIND_RESET,
+    KIND_SET_PRIORITY,
+    KIND_SET_AFFINITY,
+    KIND_BLOCK,
+    KIND_UNBLOCK
+  } kind;
+
+  size_t index;
+
+  struct {
+    rtems_task_priority priority;
+    uint32_t cpu_set;
+  } data;
+
+  uint8_t expected_cpu_allocations[CPU_COUNT];
+} test_action;
+
+typedef struct {
+  rtems_id timer_id;
+  rtems_id master_id;
+  rtems_id task_ids[TASK_COUNT];
+  size_t action_index;
+} test_context;
+
+#define RESET \
+  { \
+    KIND_RESET, \
+    0, \
+    { 0 }, \
+    { IDLE, IDLE, IDLE, IDLE } \
+  }
+
+#define SET_PRIORITY(index, prio, cpu0, cpu1, cpu2, cpu3) \
+  { \
+    KIND_SET_PRIORITY, \
+    index, \
+    { .priority = prio }, \
+    { cpu0, cpu1, cpu2, cpu3 } \
+  }
+
+#define SET_AFFINITY(index, aff, cpu0, cpu1, cpu2, cpu3) \
+  { \
+    KIND_SET_AFFINITY, \
+    index, \
+    { .cpu_set = aff }, \
+    { cpu0, cpu1, cpu2, cpu3 } \
+  }
+
+#define BLOCK(index, cpu0, cpu1, cpu2, cpu3) \
+  { \
+    KIND_BLOCK, \
+    index, \
+    { 0 }, \
+    { cpu0, cpu1, cpu2, cpu3 } \
+  }
+
+#define UNBLOCK(index, cpu0, cpu1, cpu2, cpu3) \
+  { \
+    KIND_UNBLOCK, \
+    index, \
+    { 0 }, \
+    { cpu0, cpu1, cpu2, cpu3 } \
+  }
+
+static const test_action test_actions[] = {
+  RESET,
+  UNBLOCK(      0,           0, IDLE, IDLE, IDLE),
+  UNBLOCK(      1,           0,    1, IDLE, IDLE),
+  UNBLOCK(      2,           0,    1,    2, IDLE),
+  UNBLOCK(      3,           0,    1,    2,    3),
+  UNBLOCK(      5,           0,    1,    2,    3),
+  SET_PRIORITY( 3,  P(4),    0,    1,    2,    3),
+  SET_PRIORITY( 5,  P(3),    0,    1,    2,    5),
+  BLOCK(        5,           0,    1,    2,    3),
+  SET_AFFINITY( 5,   ALL,    0,    1,    2,    3),
+  RESET,
+  UNBLOCK(      0,           0, IDLE, IDLE, IDLE),
+  RESET
+};
+
+static test_context test_instance;
+
+static void set_priority(rtems_id id, rtems_task_priority prio)
+{
+  rtems_status_code sc;
+
+  sc = rtems_task_set_priority(id, prio, &prio);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void set_affinity(rtems_id id, uint32_t cpu_set_32)
+{
+  rtems_status_code sc;
+  cpu_set_t cpu_set;
+  size_t i;
+
+  CPU_ZERO(&cpu_set);
+
+  for (i = 0; i < CPU_COUNT; ++i) {
+    uint32_t one;
+
+    one = 1;
+
+    if ((cpu_set_32 & (one << i)) != 0) {
+      CPU_SET(i, &cpu_set);
+    }
+  }
+
+  sc = rtems_task_set_affinity(id, sizeof(cpu_set), &cpu_set);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void reset(test_context *ctx)
+{
+  rtems_status_code sc;
+  size_t i;
+
+  for (i = CPU_COUNT; i < TASK_COUNT; ++i) {
+    set_priority(ctx->task_ids[i], P(i));
+    set_affinity(ctx->task_ids[i], ALL);
+
+    sc = rtems_task_suspend(ctx->task_ids[i]);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_ALREADY_SUSPENDED);
+  }
+
+  for (i = 0; i < CPU_COUNT; ++i) {
+    set_priority(ctx->task_ids[i], P(i));
+
+    sc = rtems_task_resume(ctx->task_ids[i]);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_INCORRECT_STATE);
+  }
+
+  /* Order the idle threads explicitly */
+  for (i = 0; i < CPU_COUNT; ++i) {
+    const Per_CPU_Control *c;
+    const Thread_Control *h;
+
+    c = _Per_CPU_Get_by_index(CPU_COUNT - 1 - i);
+    h = c->heir;
+
+    sc = rtems_task_suspend(h->Object.id);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  }
+}
+
+static void check_cpu_allocations(test_context *ctx, const test_action *action)
+{
+  size_t i;
+
+  for (i = 0; i < CPU_COUNT; ++i) {
+    size_t e;
+    const Per_CPU_Control *c;
+    const Thread_Control *h;
+
+    e = action->expected_cpu_allocations[i];
+    c = _Per_CPU_Get_by_index(i);
+    h = c->heir;
+
+    if (e != IDLE) {
+      rtems_test_assert(h->Object.id == ctx->task_ids[e]);
+    } else {
+      rtems_test_assert(h->Start.Entry.adaptor == _Thread_Entry_adaptor_idle);
+    }
+  }
+}
+
+/*
+ * Use a timer to execute the actions, since it runs with thread dispatching
+ * disabled.  This is necessary to check the expected processor allocations.
+ */
+static void timer(rtems_id id, void *arg)
+{
+  test_context *ctx;
+  rtems_status_code sc;
+  size_t i;
+
+  ctx = arg;
+  i = ctx->action_index;
+
+  if (i == 0) {
+    sc = rtems_task_suspend(ctx->master_id);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  }
+
+  if (i < RTEMS_ARRAY_SIZE(test_actions)) {
+    const test_action *action = &test_actions[i];
+    rtems_id task;
+
+    ctx->action_index = i + 1;
+
+    task = ctx->task_ids[action->index];
+
+    switch (action->kind) {
+      case KIND_SET_PRIORITY:
+        set_priority(task, action->data.priority);
+        break;
+      case KIND_SET_AFFINITY:
+        set_affinity(task, action->data.cpu_set);
+        break;
+      case KIND_BLOCK:
+        sc = rtems_task_suspend(task);
+        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+        break;
+      case KIND_UNBLOCK:
+        sc = rtems_task_resume(task);
+        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+        break;
+      default:
+        rtems_test_assert(action->kind == KIND_RESET);
+        reset(ctx);
+        break;
+    }
+
+    check_cpu_allocations(ctx, action);
+
+    sc = rtems_timer_reset(id);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  } else {
+    sc = rtems_task_resume(ctx->master_id);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+    sc = rtems_event_transient_send(ctx->master_id);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  }
+}
+
+static void do_nothing_task(rtems_task_argument arg)
+{
+  (void) arg;
+
+  while (true) {
+    /* Do nothing */
+  }
+}
+
 static void test(void)
 {
+  test_context *ctx;
+  rtems_status_code sc;
+  size_t i;
+
+  ctx = &test_instance;
+
+  ctx->master_id = rtems_task_self();
+
+  for (i = 0; i < TASK_COUNT; ++i) {
+    sc = rtems_task_create(
+      NAME,
+      P(i),
+      RTEMS_MINIMUM_STACK_SIZE,
+      RTEMS_DEFAULT_MODES,
+      RTEMS_DEFAULT_ATTRIBUTES,
+      &ctx->task_ids[i]
+    );
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+    sc = rtems_task_start(ctx->task_ids[i], do_nothing_task, 0);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  }
+
+  sc = rtems_timer_create(NAME, &ctx->timer_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_timer_fire_after(ctx->timer_id, 1, timer, ctx);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  for (i = 0; i < TASK_COUNT; ++i) {
+    sc = rtems_task_delete(ctx->task_ids[i]);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  }
+
+  sc = rtems_timer_delete(ctx->timer_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 }
 
 static void Init(rtems_task_argument arg)
 {
   TEST_BEGIN();
 
-  test();
+  if (rtems_get_processor_count() == CPU_COUNT) {
+    test();
+  } else {
+    puts("warning: wrong processor count to run the test");
+  }
 
   TEST_END();
   rtems_test_exit(0);
 }
 
+#define CONFIGURE_MICROSECONDS_PER_TICK 1000
+
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
 
-#define CONFIGURE_MAXIMUM_TASKS 1
+#define CONFIGURE_MAXIMUM_TASKS (1 + TASK_COUNT)
+#define CONFIGURE_MAXIMUM_TIMERS 1
 
 #define CONFIGURE_SMP_APPLICATION
 
-#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 2
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
 
 #define CONFIGURE_SCHEDULER_STRONG_APA
 



More information about the vc mailing list