[PATCH 02/12] spcache01: Add test for multiprocessor extensions

Gedare Bloom gedare at rtems.org
Tue May 27 14:47:14 UTC 2014


This spcache01 test is getting quite large. Does it make sense to split it up?

On Tue, May 27, 2014 at 10:44 AM, Ralf Kirchner
<ralf.kirchner at embedded-brains.de> wrote:
> Add test which ensures that a cache invalidate executed by one processor is seen by another processor
> ---
>  testsuites/sptests/spcache01/init.c |  209 +++++++++++++++++++++++++++++++----
>  1 Datei geändert, 185 Zeilen hinzugefügt(+), 24 Zeilen entfernt(-)
>
> diff --git a/testsuites/sptests/spcache01/init.c b/testsuites/sptests/spcache01/init.c
> index 303f7f6..99f5ec4 100644
> --- a/testsuites/sptests/spcache01/init.c
> +++ b/testsuites/sptests/spcache01/init.c
> @@ -21,6 +21,8 @@
>
>  #include <rtems.h>
>  #include <rtems/counter.h>
> +#include <rtems/score/smpbarrier.h>
> +#include <rtems/rtems/smp.h>
>
>  #define TESTS_USE_PRINTF
>  #include "tmacros.h"
> @@ -35,7 +37,145 @@ const char rtems_test_name[] = "SPCACHE 1";
>
>  #define I512() I64(); I64(); I64(); I64(); I64(); I64(); I64(); I64()
>
> -CPU_STRUCTURE_ALIGNMENT static int data[1024];
> +#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
> +
> +typedef struct {
> +#if defined( RTEMS_SMP )
> +  SMP_barrier_Control barrier;
> +#endif /* defined( RTEMS_SMP ) */
> +  CPU_STRUCTURE_ALIGNMENT int data[1024];
> +} test_context;
> +
> +static test_context test_instance;
> +
> +#if defined( RTEMS_SMP )
> +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 *data = &test_instance.data[0];
> +
> +  (void)arg;
> +
> +
> +  rtems_interrupt_lock_initialize(&lock, "test");
> +  rtems_interrupt_lock_acquire(&lock, &lock_context);
> +
> +  /* Wait for the other task to start it's initialization */
> +  _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(
> +    &data[0],
> +    sizeof(data[0])
> +  );
> +
> +  /* Wait for the other task to complete it's initialization */
> +  _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT);
> +
> +  /* Wait for the other task to complete preparations for the invalidation */
> +  _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(
> +    &data[0],
> +    sizeof(data[0])
> +  );
> +
> +  /* Signal that we have completed the invalidation */
> +  _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( const bool write_through )
> +{
> +#if defined( RTEMS_SMP )
> +  if( ( ! write_through ) && ( rtems_get_processor_count() > 1 ) ) {
> +    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 = &test_instance.data[0];
> +    volatile int *vdata = &test_instance.data[0];
> +    rtems_status_code sc;
> +    const int PATTERN = 0x89ABCDEF;
> +
> +    printf("test for multiprocessor extensions handling\n");
> +
> +    _SMP_barrier_Control_initialize( &test_instance.barrier );
> +
> +    rtems_interrupt_lock_initialize(&lock, "test");
> +    rtems_interrupt_lock_acquire(&lock, &lock_context);
> +
> +    /* Create and start another task for our test. As we are under SMP conditions,
> +    * this new task will be operating on another processor */
> +    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);
> +
> +    /* Permit the other task to start it's initialization */
> +    _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])
> +    );
> +
> +    /* Wait for the other task to complete it's initialization */
> +    _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT);
> +
> +    /* Initialize */
> +    vdata[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 */
> +    vdata[0] = ~PATTERN;
> +
> +    /* Have the other task invalidate the cache line */
> +    _SMP_barrier_Wait(&test_instance.barrier, &bs, TEST_SMP_PROCESSOR_COUNT);
> +
> +    /* Wait for the complation of the invalidation by the other task */
> +    _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(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 )
>  {
> @@ -43,12 +183,20 @@ static void test_misalignment( const bool write_through )
>      rtems_interrupt_lock lock;
>      rtems_interrupt_lock_context lock_context;
>      const uint32_t LINE_SIZE  = rtems_cache_get_data_line_size();
> -    volatile int *vdata = &data[0]; /* Verification start address */
> -    int *tdata = &data[LINE_SIZE / sizeof(data[0])]; /* test start address (first word in second cache line) */
> +    int *data = &data[0];
> +    /* Verification start address */
> +    volatile int *vdata = data;
> +    /* test start address (first word in second cache line) */
> +    int *tdata = &data[LINE_SIZE / sizeof(data[0])];
>      int tcount = 1; /* Words to be tested */
> -    size_t tdata_bytes = tcount * sizeof(data[0]); /* Bytes to be tested */
> -    size_t vdata_bytes = LINE_SIZE; /* Bytes expected to be affected by cache maintenance */
> -    int vcount = (vdata_bytes / sizeof(data[0])) + (2 * LINE_SIZE / sizeof(data[0])); /* Words to be verified (Words affected + 2 adjacent cache lines) */
> +    /* Bytes to be tested */
> +    size_t tdata_bytes = tcount * sizeof(data[0]);
> +    /* Bytes expected to be affected by cache maintenance */
> +    size_t vdata_bytes = LINE_SIZE;
> +    /* Words to be verified (Words affected + 2 adjacent cache lines) */
> +    int vcount =
> +      (vdata_bytes / sizeof(data[0]))
> +      + (2 * LINE_SIZE / sizeof(data[0]));
>      int i;
>      int end;
>
> @@ -174,7 +322,8 @@ static void test_misalignment( const bool write_through )
>       * The modified line shall get invalidated/flushed entirely,
>       * adjacent cache lines shall remain unchanged.
>       */
> -    tdata = &data[(LINE_SIZE / sizeof(data[0])) + ((LINE_SIZE / sizeof(data[0])) -1)];
> +    tdata = &data[(LINE_SIZE / sizeof(data[0]))
> +                  + ((LINE_SIZE / sizeof(data[0])) -1)];
>
>      for (i = 0; i < vcount; ++i) {
>        vdata[i] = i;
> @@ -232,10 +381,12 @@ static void test_misalignment( const bool write_through )
>       * The modified lines shall get invalidated/flushed entirely,
>       * adjacent cache lines shall remain unchanged.
>       */
> -    tdata = &data[(LINE_SIZE / sizeof(data[0])) + ((LINE_SIZE / sizeof(data[0])) -1)];
> +    tdata = &data[(LINE_SIZE / sizeof(data[0]))
> +                  + ((LINE_SIZE / sizeof(data[0])) -1)];
>      vdata_bytes = LINE_SIZE * 2;
>      tcount = 2;
> -    vcount = (vdata_bytes / sizeof(data[0])) + (2 * LINE_SIZE / sizeof(data[0]));
> +    vcount = (vdata_bytes / sizeof(data[0]))
> +             + (2 * LINE_SIZE / sizeof(data[0]));
>      tdata_bytes = tcount * sizeof(data[0]);
>
>      for (i = 0; i < vcount; ++i) {
> @@ -292,13 +443,14 @@ static void test_misalignment( const bool write_through )
>      rtems_interrupt_lock_destroy(&lock);
>
>      printf(
> -      "data cache operations with misaligned addresses passed the test (%s cache detected)\n",
> -           write_through ? "write-through" : "copy-back"
> +      "data cache operations with misaligned addresses passed the test "
> +      "(%s cache detected)\n",
> +      write_through ? "write-through" : "copy-back"
>      );
>    } else {
>      printf(
> -      "skip data cache flush and invalidate test with misaligned addresses"
> -      " due to cache line size of zero\n"
> +      "skip data cache flush and invalidate test with "
> +      "misaligned addresses due to cache line size of zero\n"
>      );
>    }
>  }
> @@ -309,7 +461,8 @@ static bool test_data_flush_and_invalidate(void)
>    if (rtems_cache_get_data_line_size() > 0) {
>      rtems_interrupt_lock lock;
>      rtems_interrupt_lock_context lock_context;
> -    volatile int *vdata = &data[0];
> +    int *data = &test_instance.data[0];
> +    volatile int *vdata = data;
>      int n = 32;
>      int i;
>      size_t data_size = n * sizeof(data[0]);
> @@ -397,7 +550,8 @@ static uint64_t load(void)
>    rtems_counter_ticks b;
>    rtems_counter_ticks d;
>    size_t i;
> -  volatile int *vdata = &data[0];
> +  int *data = &test_instance.data[0];
> +  volatile int *vdata = data;
>
>    a = rtems_counter_read();
>    for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
> @@ -416,10 +570,10 @@ static uint64_t store(void)
>    rtems_counter_ticks b;
>    rtems_counter_ticks d;
>    size_t i;
> -  volatile int *vdata = &data[0];
> +  volatile int *vdata = &test_instance.data[0];
>
>    a = rtems_counter_read();
> -  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
> +  for (i = 0; i < RTEMS_ARRAY_SIZE(test_instance.data); ++i) {
>      vdata[i] = 0;
>    }
>    b = rtems_counter_read();
> @@ -433,7 +587,8 @@ static void test_timing(void)
>  {
>    rtems_interrupt_lock lock;
>    rtems_interrupt_lock_context lock_context;
> -  size_t data_size = sizeof(data);
> +  int *data = &test_instance.data[0];
> +  size_t data_size = sizeof(test_instance.data);
>    uint64_t d[3];
>    uint32_t cache_level;
>    size_t cache_size;
> @@ -483,7 +638,7 @@ static void test_timing(void)
>
>    d[0] = load();
>    d[1] = load();
> -  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
> +  rtems_cache_flush_multiple_data_lines(data, sizeof(test_instance.data));
>    d[2] = load();
>
>    rtems_interrupt_lock_release(&lock, &lock_context);
> @@ -503,7 +658,7 @@ static void test_timing(void)
>
>    d[0] = load();
>    d[1] = load();
> -  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
> +  rtems_cache_invalidate_multiple_data_lines(data, sizeof(test_instance.data));
>    d[2] = load();
>
>    rtems_interrupt_lock_release(&lock, &lock_context);
> @@ -543,7 +698,7 @@ static void test_timing(void)
>
>    d[0] = store();
>    d[1] = store();
> -  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
> +  rtems_cache_flush_multiple_data_lines(data, sizeof(test_instance.data));
>    d[2] = store();
>
>    rtems_interrupt_lock_release(&lock, &lock_context);
> @@ -563,7 +718,7 @@ static void test_timing(void)
>
>    d[0] = store();
>    d[1] = store();
> -  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
> +  rtems_cache_invalidate_multiple_data_lines(data, sizeof(test_instance.data));
>    d[2] = store();
>
>    rtems_interrupt_lock_release(&lock, &lock_context);
> @@ -647,18 +802,24 @@ static void Init(rtems_task_argument arg)
>    write_through = test_data_flush_and_invalidate();
>    test_misalignment( write_through );
>    test_timing();
> +  test_multiprocessor_extensions(write_through);
>
>    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 at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel




More information about the devel mailing list