forked from Imagelibrary/rtems
smptests/smpmigration02: PR2183: Add test case
This commit is contained in:
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <rtems/libcsupport.h>
|
#include <rtems/libcsupport.h>
|
||||||
|
#include <rtems/score/objectimpl.h>
|
||||||
|
#include <rtems/score/threadimpl.h>
|
||||||
|
|
||||||
#include "tmacros.h"
|
#include "tmacros.h"
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ typedef struct {
|
|||||||
|
|
||||||
static test_context test_instance;
|
static test_context test_instance;
|
||||||
|
|
||||||
static void task(rtems_task_argument arg)
|
static void migration_task(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
test_context *ctx = &test_instance;
|
test_context *ctx = &test_instance;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -63,20 +65,13 @@ static void task(rtems_task_argument arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test(void)
|
static void test_migrations(test_context *ctx)
|
||||||
{
|
{
|
||||||
test_context *ctx = &test_instance;
|
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
uint32_t cpu_count = rtems_get_processor_count();
|
uint32_t cpu_count = rtems_get_processor_count();
|
||||||
uint32_t cpu_index;
|
|
||||||
uint32_t task_count = cpu_count + 1;
|
uint32_t task_count = cpu_count + 1;
|
||||||
uint32_t task_index;
|
uint32_t task_index;
|
||||||
|
|
||||||
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
|
|
||||||
sc = rtems_scheduler_ident(cpu_index, &ctx->scheduler_ids[cpu_index]);
|
|
||||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (task_index = 0; task_index < task_count; ++task_index) {
|
for (task_index = 0; task_index < task_count; ++task_index) {
|
||||||
rtems_id task_id;
|
rtems_id task_id;
|
||||||
|
|
||||||
@@ -93,7 +88,7 @@ static void test(void)
|
|||||||
sc = rtems_task_set_scheduler(task_id, ctx->scheduler_ids[task_index % cpu_count]);
|
sc = rtems_task_set_scheduler(task_id, ctx->scheduler_ids[task_index % cpu_count]);
|
||||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
sc = rtems_task_start(task_id, task, task_index);
|
sc = rtems_task_start(task_id, migration_task, task_index);
|
||||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
ctx->task_ids[task_index] = task_id;
|
ctx->task_ids[task_index] = task_id;
|
||||||
@@ -114,15 +109,147 @@ static void test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void busy_loop_task(rtems_task_argument arg)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Thread_Control *get_thread_by_id(rtems_id task_id)
|
||||||
|
{
|
||||||
|
Objects_Locations location;
|
||||||
|
Thread_Control *thread;
|
||||||
|
|
||||||
|
thread = _Thread_Get(task_id, &location);
|
||||||
|
rtems_test_assert(location == OBJECTS_LOCAL);
|
||||||
|
_Thread_Enable_dispatch();
|
||||||
|
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_double_migration(test_context *ctx)
|
||||||
|
{
|
||||||
|
uint32_t cpu_count = rtems_get_processor_count();
|
||||||
|
|
||||||
|
if (cpu_count >= 2) {
|
||||||
|
rtems_status_code sc;
|
||||||
|
rtems_id task_id;
|
||||||
|
rtems_id scheduler_id;
|
||||||
|
uint32_t cpu_self_index = 0;
|
||||||
|
uint32_t cpu_other_index = 1;
|
||||||
|
Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(cpu_self_index);
|
||||||
|
Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index(cpu_other_index);
|
||||||
|
Thread_Control *self;
|
||||||
|
Thread_Control *other;
|
||||||
|
|
||||||
|
sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
rtems_test_assert(scheduler_id == ctx->scheduler_ids[cpu_self_index]);
|
||||||
|
|
||||||
|
sc = rtems_task_create(
|
||||||
|
rtems_build_name('T', 'A', 'S', 'K'),
|
||||||
|
2,
|
||||||
|
RTEMS_MINIMUM_STACK_SIZE,
|
||||||
|
RTEMS_DEFAULT_MODES,
|
||||||
|
RTEMS_DEFAULT_ATTRIBUTES,
|
||||||
|
&task_id
|
||||||
|
);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
other = get_thread_by_id(task_id);
|
||||||
|
|
||||||
|
sc = rtems_task_set_scheduler(
|
||||||
|
task_id,
|
||||||
|
ctx->scheduler_ids[cpu_other_index]
|
||||||
|
);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
sc = rtems_task_start(task_id, busy_loop_task, 0);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
while (!_Thread_Is_executing_on_a_processor(other)) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
_Thread_Disable_dispatch();
|
||||||
|
|
||||||
|
self = _Thread_Executing;
|
||||||
|
|
||||||
|
rtems_test_assert(cpu_self->executing == self);
|
||||||
|
rtems_test_assert(cpu_self->heir == self);
|
||||||
|
rtems_test_assert(!cpu_self->dispatch_necessary);
|
||||||
|
|
||||||
|
rtems_test_assert(cpu_other->executing == other);
|
||||||
|
rtems_test_assert(cpu_other->heir == other);
|
||||||
|
rtems_test_assert(!cpu_other->dispatch_necessary);
|
||||||
|
|
||||||
|
sc = rtems_task_set_scheduler(
|
||||||
|
RTEMS_SELF,
|
||||||
|
ctx->scheduler_ids[cpu_other_index]
|
||||||
|
);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
rtems_test_assert(cpu_self->executing == self);
|
||||||
|
rtems_test_assert(cpu_self->heir != self);
|
||||||
|
rtems_test_assert(cpu_self->dispatch_necessary);
|
||||||
|
|
||||||
|
while (_Thread_Is_executing_on_a_processor(other)) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_test_assert(cpu_other->executing == self);
|
||||||
|
rtems_test_assert(cpu_other->heir == self);
|
||||||
|
rtems_test_assert(!cpu_other->dispatch_necessary);
|
||||||
|
|
||||||
|
sc = rtems_task_set_scheduler(
|
||||||
|
RTEMS_SELF,
|
||||||
|
ctx->scheduler_ids[cpu_self_index]
|
||||||
|
);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
rtems_test_assert(cpu_self->executing == self);
|
||||||
|
rtems_test_assert(cpu_self->heir == self);
|
||||||
|
rtems_test_assert(cpu_self->dispatch_necessary);
|
||||||
|
|
||||||
|
rtems_test_assert(cpu_other->heir == other);
|
||||||
|
|
||||||
|
_Thread_Enable_dispatch();
|
||||||
|
|
||||||
|
while (!_Thread_Is_executing_on_a_processor(other)) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
sc = rtems_task_delete(task_id);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_scheduler_ids(test_context *ctx)
|
||||||
|
{
|
||||||
|
rtems_status_code sc;
|
||||||
|
uint32_t cpu_count = rtems_get_processor_count();
|
||||||
|
uint32_t cpu_index;
|
||||||
|
|
||||||
|
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
|
||||||
|
sc = rtems_scheduler_ident(cpu_index, &ctx->scheduler_ids[cpu_index]);
|
||||||
|
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void Init(rtems_task_argument arg)
|
static void Init(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
|
test_context *ctx = &test_instance;
|
||||||
rtems_resource_snapshot snapshot;
|
rtems_resource_snapshot snapshot;
|
||||||
|
|
||||||
TEST_BEGIN();
|
TEST_BEGIN();
|
||||||
|
|
||||||
rtems_resource_snapshot_take(&snapshot);
|
rtems_resource_snapshot_take(&snapshot);
|
||||||
|
|
||||||
test();
|
init_scheduler_ids(ctx);
|
||||||
|
test_double_migration(ctx);
|
||||||
|
test_migrations(ctx);
|
||||||
|
|
||||||
rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
|
rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user