Add test which ensures that a cache invalidate executed by one processor is seen by another processor --- testsuites/sptests/spcache01/init.c | 143 ++++++++++++++++++++++++++++++++++- 1 Datei geändert, 141 Zeilen hinzugefügt(+), 2 Zeilen entfernt(-)
diff --git a/testsuites/sptests/spcache01/init.c b/testsuites/sptests/spcache01/init.c index 303f7f6..57dd0e7 100644 --- a/testsuites/sptests/spcache01/init.c +++ b/testsuites/sptests/spcache01/init.c @@ -21,6 +21,7 @@ #include <rtems.h> #include <rtems/counter.h> +#include <rtems/score/smpbarrier.h> #define TESTS_USE_PRINTF #include "tmacros.h" @@ -35,8 +36,140 @@ const char rtems_test_name[] = "SPCACHE 1"; #define I512() I64(); I64(); I64(); I64(); I64(); I64(); I64(); I64() +#if defined( RTEMS_SMP ) + #define TEST_SMP_TASK_COUNT 1 +#else + #define TEST_SMP_TASK_COUNT 0 +#endif /* defined( RTEMS_SMP ) */ + +#define TEST_SMP_PROCESSOR_COUNT 2 + +#define TASK_PRIORITY 1 + CPU_STRUCTURE_ALIGNMENT static int data[1024]; +#if defined( RTEMS_SMP ) +typedef enum { + TEST_STATUS_INITIALIZING, + TEST_STATUS_EVALUATING, + TEST_STATUS_FINISHED +} test_status; + +typedef struct { + SMP_barrier_Control barrier; + test_status status; + volatile int *vdata; +} test_context; + +static test_context test_instance = { + SMP_BARRIER_CONTROL_INITIALIZER, + TEST_STATUS_INITIALIZING, + &data[0] /* Verification start address */ +}; + +static rtems_task test_multiprocessor_extensions_task( rtems_task_argument arg ) +{ + SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER; + rtems_interrupt_lock lock; + rtems_interrupt_lock_context lock_context; + int *tdata = &data[0]; + + (void)arg; + rtems_interrupt_lock_initialize(&lock, "test"); + rtems_interrupt_lock_acquire(&lock, &lock_context); + + _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT); + + /* Make sure we don't have the cache line cached */ + rtems_cache_invalidate_multiple_data_lines( + &tdata[0], + sizeof(tdata[0]) + ); + + _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT); + + /* Now the other task should also get the cache line invalidated */ + rtems_cache_invalidate_multiple_data_lines( + &tdata[0], + sizeof(tdata[0]) + ); + test_instance.status = TEST_STATUS_FINISHED; + + _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT); + + rtems_interrupt_lock_release(&lock, &lock_context); + rtems_interrupt_lock_destroy(&lock); + + rtems_task_delete(RTEMS_SELF); +} +#endif /* defined( RTEMS_SMP ) */ + +static void test_multiprocessor_extensions( void ) +{ +#if defined( RTEMS_SMP ) + rtems_interrupt_lock lock; + rtems_interrupt_lock_context lock_context; + SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER; + rtems_id id_work1 = RTEMS_ID_NONE; + int *tdata = &data[0]; + rtems_status_code sc; + const int PATTERN = 0x89ABCDEF; + + printf("test for multiprocessor extensions handling\n"); + + + rtems_interrupt_lock_initialize(&lock, "test"); + rtems_interrupt_lock_acquire(&lock, &lock_context); + + sc = rtems_task_create( + rtems_build_name('W', 'R', 'K', '1'), + TASK_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id_work1 + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id_work1, test_multiprocessor_extensions_task, 0); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT); + + /* Make sure we don't have the cache line cached */ + rtems_cache_invalidate_multiple_data_lines( + &tdata[0], + sizeof(tdata[0]) + ); + + /* Initialize */ + tdata[0] = PATTERN; + + /* Flush initialized cache line to RAM */ + rtems_cache_flush_multiple_data_lines( + &tdata[0], + sizeof(tdata[0]) + ); + + /* Modify cache line in cache only */ + tdata[0] = ~PATTERN; + + /* Have the other task invalidate the cache line */ + test_instance.status = TEST_STATUS_EVALUATING; + _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT); + + _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT); + + /* The other task has invalidated the cache, thus we should read what was flushed to RAM */ + rtems_test_assert(test_instance.vdata[0] == PATTERN); + + rtems_interrupt_lock_release(&lock, &lock_context); + rtems_interrupt_lock_destroy(&lock); + + printf("test for multiprocessor extensions passed\n"); +#endif /* defined( RTEMS_SMP ) */ +} + static void test_misalignment( const bool write_through ) { if (rtems_cache_get_data_line_size() > 0) { @@ -647,18 +780,24 @@ static void Init(rtems_task_argument arg) write_through = test_data_flush_and_invalidate(); test_misalignment( write_through ); test_timing(); + test_multiprocessor_extensions(); TEST_END(); rtems_test_exit(0); } -#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#if defined( RTEMS_SMP ) + #define CONFIGURE_SMP_APPLICATION + #define CONFIGURE_SMP_MAXIMUM_PROCESSORS 32 +#endif /* defined( RTEMS_SMP ) */ +#define CONFIGURE_INIT_TASK_PRIORITY TASK_PRIORITY +#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER #define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM -#define CONFIGURE_MAXIMUM_TASKS 1 +#define CONFIGURE_MAXIMUM_TASKS (1 + TEST_SMP_TASK_COUNT) #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION -- 1.7.10.4 _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel