[PATCH 1/3] score: Add flexible per-CPU data

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Sep 7 13:48:19 UTC 2018


Update #3507.
---
 cpukit/headers.am                                  |   1 +
 cpukit/include/rtems/score/percpu.h                |   9 +-
 cpukit/include/rtems/score/percpudata.h            | 104 ++++++++
 cpukit/score/src/wkspace.c                         | 128 +++++++--
 testsuites/sptests/Makefile.am                     |   9 +
 testsuites/sptests/configure.ac                    |   1 +
 testsuites/sptests/sppercpudata01/init.c           | 290 +++++++++++++++++++++
 testsuites/sptests/sppercpudata01/item.c           |  21 ++
 .../sptests/sppercpudata01/sppercpudata01.doc      |  13 +
 testsuites/sptests/sppercpudata01/sppercpudata01.h |  30 +++
 .../sptests/sppercpudata01/sppercpudata01.scn      |   7 +
 11 files changed, 591 insertions(+), 22 deletions(-)
 create mode 100644 cpukit/include/rtems/score/percpudata.h
 create mode 100644 testsuites/sptests/sppercpudata01/init.c
 create mode 100644 testsuites/sptests/sppercpudata01/item.c
 create mode 100644 testsuites/sptests/sppercpudata01/sppercpudata01.doc
 create mode 100644 testsuites/sptests/sppercpudata01/sppercpudata01.h
 create mode 100644 testsuites/sptests/sppercpudata01/sppercpudata01.scn

diff --git a/cpukit/headers.am b/cpukit/headers.am
index 303dbc58a7..a848690e3a 100644
--- a/cpukit/headers.am
+++ b/cpukit/headers.am
@@ -375,6 +375,7 @@ include_rtems_score_HEADERS += include/rtems/score/objectimpl.h
 include_rtems_score_HEADERS += include/rtems/score/objectmp.h
 include_rtems_score_HEADERS += include/rtems/score/onceimpl.h
 include_rtems_score_HEADERS += include/rtems/score/percpu.h
+include_rtems_score_HEADERS += include/rtems/score/percpudata.h
 include_rtems_score_HEADERS += include/rtems/score/priority.h
 include_rtems_score_HEADERS += include/rtems/score/prioritybitmap.h
 include_rtems_score_HEADERS += include/rtems/score/prioritybitmapimpl.h
diff --git a/cpukit/include/rtems/score/percpu.h b/cpukit/include/rtems/score/percpu.h
index f0b155d4c1..712d1cde36 100644
--- a/cpukit/include/rtems/score/percpu.h
+++ b/cpukit/include/rtems/score/percpu.h
@@ -9,7 +9,7 @@
  *  COPYRIGHT (c) 1989-2011.
  *  On-Line Applications Research Corporation (OAR).
  *
- *  Copyright (c) 2012, 2016 embedded brains GmbH
+ *  Copyright (c) 2012, 2018 embedded brains GmbH
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -477,6 +477,13 @@ typedef struct Per_CPU_Control {
     } Scheduler;
 
     /**
+     * @brief Begin of the per-CPU data area.
+     *
+     * Contains items defined via PER_CPU_DATA_ITEM().
+     */
+    char *data;
+
+    /**
      * @brief Indicates the current state of the CPU.
      *
      * This field is protected by the _Per_CPU_State_lock lock.
diff --git a/cpukit/include/rtems/score/percpudata.h b/cpukit/include/rtems/score/percpudata.h
new file mode 100644
index 0000000000..3de99566ad
--- /dev/null
+++ b/cpukit/include/rtems/score/percpudata.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_PERCPUDATA_H
+#define _RTEMS_SCORE_PERCPUDATA_H
+
+#include <rtems/score/percpu.h>
+#include <rtems/linkersets.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup PerCPUData Flexible Per-CPU Data
+ *
+ * @ingroup PerCPU
+ *
+ * Provides the definition of custom per-CPU items.  The items are collected in
+ * a special linker set.  During system initialization the content of the
+ * linker set is duplicated for all secondary processors using memory allocated
+ * from the workspace.  The begin and end of the per-CPU data area is cache
+ * line aligned (CPU_CACHE_LINE_BYTES).
+ *
+ * @{
+ */
+
+RTEMS_LINKER_RWSET_DECLARE( _Per_CPU_Data, char );
+
+/**
+ * @brief Declares a per-CPU item of the specified type.
+ *
+ * Items declared with this macro have external linkage.
+ *
+ * @param type The type of the item.
+ * @param item The designator of the item.
+ */
+#define PER_CPU_DATA_ITEM_DECLARE( type, item ) \
+  RTEMS_LINKER_RWSET_ITEM_DECLARE( _Per_CPU_Data, type, item )
+
+/**
+ * @brief Defines a per-CPU item of the specified type.
+ *
+ * @param type The type of the item.
+ * @param item The designator of the item.
+ */
+#define PER_CPU_DATA_ITEM( type, item ) \
+  RTEMS_LINKER_RWSET_ITEM( _Per_CPU_Data, type, item )
+
+/**
+ * @brief Returns the offset of the per-CPU item to the begin of the per-CPU
+ * data area.
+ *
+ * @param item The designator of the item.
+ */
+#define PER_CPU_DATA_OFFSET( item ) \
+  ( (uintptr_t) &_Linker_set__Per_CPU_Data_##item \
+    - (uintptr_t) RTEMS_LINKER_SET_BEGIN( _Per_CPU_Data ) )
+
+/**
+ * @brief Returns a pointer of the specified type to the per-CPU item at the
+ * specified offset for the specified processor.
+ *
+ * @param cpu The processor of the item.
+ * @param type The type of the item.
+ * @param offset The offset of the item.
+ */
+#define PER_CPU_DATA_GET_BY_OFFSET( cpu, type, offset ) \
+  (type *) ( cpu->data + offset )
+
+/**
+ * @brief Returns a pointer of the specified type to the specified per-CPU item
+ * for the specified processor.
+ *
+ * @param cpu The processor of the item.
+ * @param type The type of the item.
+ * @param item The designator of the item.
+ */
+#ifdef RTEMS_SMP
+#define PER_CPU_DATA_GET( cpu, type, item ) \
+  PER_CPU_DATA_GET_BY_OFFSET( cpu, type, PER_CPU_DATA_OFFSET( item ) )
+#else
+#define PER_CPU_DATA_GET( cpu, type, item ) \
+  &_Linker_set__Per_CPU_Data_##item
+#endif
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_PERCPUDATA_H */
diff --git a/cpukit/score/src/wkspace.c b/cpukit/score/src/wkspace.c
index 13dfc03706..823e357009 100644
--- a/cpukit/score/src/wkspace.c
+++ b/cpukit/score/src/wkspace.c
@@ -19,25 +19,33 @@
 #endif
 
 #include <rtems/score/wkspace.h>
+#include <rtems/score/assert.h>
 #include <rtems/score/heapimpl.h>
 #include <rtems/score/interr.h>
+#include <rtems/score/percpudata.h>
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/tls.h>
 #include <rtems/config.h>
 
-#include <string.h>  /* for memset */
+#include <string.h>
 
 /* #define DEBUG_WORKSPACE */
 #if defined(DEBUG_WORKSPACE)
   #include <rtems/bspIo.h>
 #endif
 
+RTEMS_LINKER_RWSET(
+  _Per_CPU_Data,
+  RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES ) char
+);
+
 Heap_Control _Workspace_Area;
 
-static uint32_t _Get_maximum_thread_count(void)
+static uint32_t _Workspace_Get_maximum_thread_count( void )
 {
-  uint32_t thread_count = 0;
+  uint32_t thread_count;
 
+  thread_count = 0;
   thread_count += _Thread_Get_maximum_internal_threads();
 
   thread_count += rtems_resource_maximum_per_allocation(
@@ -53,20 +61,12 @@ static uint32_t _Get_maximum_thread_count(void)
   return thread_count;
 }
 
-void _Workspace_Handler_initialization(
-  Heap_Area *areas,
-  size_t area_count,
-  Heap_Initialization_or_extend_handler extend
-)
+static uintptr_t _Workspace_Space_for_TLS( uintptr_t page_size )
 {
-  Heap_Initialization_or_extend_handler init_or_extend = _Heap_Initialize;
-  uintptr_t remaining = rtems_configuration_get_work_space_size();
-  bool do_zero = rtems_configuration_get_do_zero_of_workspace();
-  bool unified = rtems_configuration_get_unified_work_area();
-  uintptr_t page_size = CPU_HEAP_ALIGNMENT;
-  uintptr_t overhead = _Heap_Area_overhead( page_size );
-  uintptr_t tls_size = _TLS_Get_size();
-  size_t i;
+  uintptr_t tls_size;
+  uintptr_t space;
+
+  tls_size = _TLS_Get_size();
 
   /*
    * In case we have a non-zero TLS size, then we need a TLS area for each
@@ -85,14 +85,99 @@ void _Workspace_Handler_initialization(
      * of a free block.  The last allocation may need one free block of minimum
      * size.
      */
-    remaining += _Heap_Min_block_size( page_size );
+    space = _Heap_Min_block_size( page_size );
 
-    remaining += _Get_maximum_thread_count()
+    space += _Workspace_Get_maximum_thread_count()
       * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
+  } else {
+    space = 0;
+  }
+
+  return space;
+}
+
+static uintptr_t _Workspace_Space_for_per_CPU_data( uintptr_t page_size )
+{
+  uintptr_t space;
+
+#ifdef RTEMS_SMP
+  uintptr_t size;
+
+  size = RTEMS_LINKER_SET_SIZE( _Per_CPU_Data );
+  _Assert( size % CPU_CACHE_LINE_BYTES == 0 );
+
+  if ( size > 0 ) {
+    /*
+     * Memory allocated with an alignment constraint is allocated from the end of
+     * a free block.  The last allocation may need one free block of minimum
+     * size.
+     */
+    space = _Heap_Min_block_size( page_size );
+
+    space += ( rtems_configuration_get_maximum_processors() - 1 )
+      * _Heap_Size_with_overhead( page_size, size, CPU_CACHE_LINE_BYTES );
+  } else {
+    space = 0;
   }
+#else
+  space = 0;
+#endif
+
+  return space;
+}
+
+static void _Workspace_Allocate_per_CPU_data( void )
+{
+#ifdef RTEMS_SMP
+  Per_CPU_Control *cpu;
+  uintptr_t        size;
+  uint32_t         cpu_index;
+  uint32_t         cpu_max;
+
+  cpu = _Per_CPU_Get_by_index( 0 );
+  cpu->data = RTEMS_LINKER_SET_BEGIN( _Per_CPU_Data );
+
+  size = RTEMS_LINKER_SET_SIZE( _Per_CPU_Data );
+  cpu_max = rtems_configuration_get_maximum_processors();
+
+  for ( cpu_index = 1 ; cpu_index < cpu_max ; ++cpu_index ) {
+    cpu = _Per_CPU_Get_by_index( cpu_index );
+    cpu->data = _Workspace_Allocate_aligned( size, CPU_CACHE_LINE_BYTES );
+    _Assert( cpu->data != NULL );
+    memcpy( cpu->data, RTEMS_LINKER_SET_BEGIN( _Per_CPU_Data ), size);
+  }
+#endif
+}
+
+void _Workspace_Handler_initialization(
+  Heap_Area *areas,
+  size_t area_count,
+  Heap_Initialization_or_extend_handler extend
+)
+{
+  Heap_Initialization_or_extend_handler init_or_extend;
+  uintptr_t                             remaining;
+  bool                                  do_zero;
+  bool                                  unified;
+  uintptr_t                             page_size;
+  uintptr_t                             overhead;
+  size_t                                i;
+
+  page_size = CPU_HEAP_ALIGNMENT;
+
+  remaining = rtems_configuration_get_work_space_size();
+  remaining += _Workspace_Space_for_TLS( page_size );
+  remaining += _Workspace_Space_for_per_CPU_data( page_size );
+
+  init_or_extend = _Heap_Initialize;
+  do_zero = rtems_configuration_get_do_zero_of_workspace();
+  unified = rtems_configuration_get_unified_work_area();
+  overhead = _Heap_Area_overhead( page_size );
+
+  for ( i = 0; i < area_count; ++i ) {
+    Heap_Area *area;
 
-  for (i = 0; i < area_count; ++i) {
-    Heap_Area *area = &areas [i];
+    area = &areas[ i ];
 
     if ( do_zero ) {
       memset( area->begin, 0, area->size );
@@ -113,7 +198,7 @@ void _Workspace_Handler_initialization(
         }
       }
 
-      space_available = (*init_or_extend)(
+      space_available = ( *init_or_extend )(
         &_Workspace_Area,
         area->begin,
         size,
@@ -138,6 +223,7 @@ void _Workspace_Handler_initialization(
   }
 
   _Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
+  _Workspace_Allocate_per_CPU_data();
 }
 
 void *_Workspace_Allocate(
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 6d28acdfbb..d9a6bf235e 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -1594,6 +1594,15 @@ sppartition_err01_CPPFLAGS = $(AM_CPPFLAGS) \
 	$(TEST_FLAGS_sppartition_err01) $(support_includes)
 endif
 
+if TEST_sppercpudata01
+sp_tests += sppercpudata01
+sp_screens += sppercpudata01/sppercpudata01.scn
+sp_docs += sppercpudata01/sppercpudata01.doc
+sppercpudata01_SOURCES = sppercpudata01/init.c sppercpudata01/item.c
+sppercpudata01_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_sppercpudata01) \
+	$(support_includes)
+endif
+
 if TEST_spport_err01
 sp_tests += spport_err01
 sp_screens += spport_err01/spport_err01.scn
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 0c9788ae1b..6418ad0bc8 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -205,6 +205,7 @@ RTEMS_TEST_CHECK([spnsext01])
 RTEMS_TEST_CHECK([spobjgetnext])
 RTEMS_TEST_CHECK([sppagesize])
 RTEMS_TEST_CHECK([sppartition_err01])
+RTEMS_TEST_CHECK([sppercpudata01])
 RTEMS_TEST_CHECK([spport_err01])
 RTEMS_TEST_CHECK([spprintk])
 RTEMS_TEST_CHECK([spprivenv01])
diff --git a/testsuites/sptests/sppercpudata01/init.c b/testsuites/sptests/sppercpudata01/init.c
new file mode 100644
index 0000000000..4c20ea7e2b
--- /dev/null
+++ b/testsuites/sptests/sppercpudata01/init.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/score/percpudata.h>
+
+#include <tmacros.h>
+
+#include "sppercpudata01.h"
+
+const char rtems_test_name[] = "SPPERCPUDATA 1";
+
+static PER_CPU_DATA_ITEM(unsigned char, c) = 1;
+
+static PER_CPU_DATA_ITEM(unsigned char, cz);
+
+static PER_CPU_DATA_ITEM(unsigned short, s) = 2;
+
+static PER_CPU_DATA_ITEM(unsigned short, sz);
+
+static PER_CPU_DATA_ITEM(unsigned int, i) = 3;
+
+static PER_CPU_DATA_ITEM(unsigned int, iz);
+
+static PER_CPU_DATA_ITEM(unsigned long, l) = 4;
+
+static PER_CPU_DATA_ITEM(unsigned long, lz);
+
+static PER_CPU_DATA_ITEM(unsigned int, a[3]) = { 5, 6, 7 };
+
+static PER_CPU_DATA_ITEM(unsigned int, az[3]);
+
+typedef struct t {
+  unsigned int a;
+  unsigned int b;
+  unsigned int c;
+} t;
+
+static PER_CPU_DATA_ITEM(t, t) = { .a = 8, .b = 9, .c = 10 };
+
+static void set_affinity(uint32_t cpu_index)
+{
+  rtems_status_code sc;
+  cpu_set_t set;
+
+  CPU_ZERO(&set);
+  CPU_SET((int) cpu_index, &set);
+  sc = rtems_task_set_affinity(RTEMS_SELF, sizeof(set), &set);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_initial_values(void)
+{
+  uint32_t cpu_index;
+
+  for (cpu_index = 0; cpu_index < rtems_get_processor_count(); ++cpu_index) {
+    Per_CPU_Control *cpu;
+    unsigned char *c;
+    unsigned short *s;
+    unsigned int *i;
+    unsigned long *l;
+    t *pt;
+
+    set_affinity(cpu_index);
+    cpu = _Per_CPU_Get_by_index(cpu_index);
+
+    c = PER_CPU_DATA_GET(cpu, unsigned char, c);
+    rtems_test_assert(*c == 1);
+
+    c = PER_CPU_DATA_GET(cpu, unsigned char, cz);
+    rtems_test_assert(*c == 0);
+
+    s = PER_CPU_DATA_GET(cpu, unsigned short, s);
+    rtems_test_assert(*s == 2);
+
+    s = PER_CPU_DATA_GET(cpu, unsigned short, sz);
+    rtems_test_assert(*s == 0);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, i);
+    rtems_test_assert(*i == 3);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, iz);
+    rtems_test_assert(*i == 0);
+
+    l = PER_CPU_DATA_GET(cpu, unsigned long, l);
+    rtems_test_assert(*l == 4);
+
+    l = PER_CPU_DATA_GET(cpu, unsigned long, lz);
+    rtems_test_assert(*l == 0);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, a[0]);
+    rtems_test_assert(i[0] == 5);
+    rtems_test_assert(i[1] == 6);
+    rtems_test_assert(i[2] == 7);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, az[0]);
+    rtems_test_assert(i[0] == 0);
+    rtems_test_assert(i[1] == 0);
+    rtems_test_assert(i[2] == 0);
+
+    pt = PER_CPU_DATA_GET(cpu, t, t);
+    rtems_test_assert(pt->a == 8);
+    rtems_test_assert(pt->b == 9);
+    rtems_test_assert(pt->c == 10);
+
+    pt = PER_CPU_DATA_GET(cpu, struct t, t);
+    rtems_test_assert(pt->a == 8);
+    rtems_test_assert(pt->b == 9);
+    rtems_test_assert(pt->c == 10);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, g);
+    rtems_test_assert(*i == 11);
+  }
+}
+
+static void set_unique_values(unsigned int v)
+{
+  uint32_t cpu_index;
+
+  for (cpu_index = 0; cpu_index < rtems_get_processor_count(); ++cpu_index) {
+    Per_CPU_Control *cpu;
+    unsigned char *c;
+    unsigned short *s;
+    unsigned int *i;
+    unsigned long *l;
+    t *pt;
+
+    set_affinity(cpu_index);
+    cpu = _Per_CPU_Get_by_index(cpu_index);
+
+    c = PER_CPU_DATA_GET(cpu, unsigned char, c);
+    *c = (unsigned char) ++v;
+
+    c = PER_CPU_DATA_GET(cpu, unsigned char, cz);
+    *c = (unsigned char) ++v;
+
+    s = PER_CPU_DATA_GET(cpu, unsigned short, s);
+    *s = (unsigned short) ++v;
+
+    s = PER_CPU_DATA_GET(cpu, unsigned short, sz);
+    *s = (unsigned short) ++v;
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, i);
+    *i = ++v;
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, iz);
+    *i = ++v;
+
+    l = PER_CPU_DATA_GET(cpu, unsigned long, l);
+    *l = ++v;
+
+    l = PER_CPU_DATA_GET(cpu, unsigned long, lz);
+    *l = ++v;
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, a[0]);
+    i[0] = ++v;
+    i[1] = ++v;
+    i[2] = ++v;
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, az[0]);
+    i[0] = ++v;
+    i[1] = ++v;
+    i[2] = ++v;
+
+    pt = PER_CPU_DATA_GET(cpu, t, t);
+    pt->a = ++v;
+    pt->b = ++v;
+    pt->c = ++v;
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, g);
+    *i = ++v;
+  }
+}
+
+static void test_unique_values(unsigned int v)
+{
+  uint32_t cpu_index;
+
+  for (cpu_index = 0; cpu_index < rtems_get_processor_count(); ++cpu_index) {
+    Per_CPU_Control *cpu;
+    unsigned char *c;
+    unsigned short *s;
+    unsigned int *i;
+    unsigned long *l;
+    t *pt;
+
+    set_affinity(cpu_index);
+    cpu = _Per_CPU_Get_by_index(cpu_index);
+
+    c = PER_CPU_DATA_GET(cpu, unsigned char, c);
+    ++v;
+    rtems_test_assert(*c == (unsigned char) v);
+
+    c = PER_CPU_DATA_GET(cpu, unsigned char, cz);
+    ++v;
+    rtems_test_assert(*c == (unsigned char) v);
+
+    s = PER_CPU_DATA_GET(cpu, unsigned short, s);
+    ++v;
+    rtems_test_assert(*s == (unsigned short) v);
+
+    s = PER_CPU_DATA_GET(cpu, unsigned short, sz);
+    ++v;
+    rtems_test_assert(*s == (unsigned short) v);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, i);
+    ++v;
+    rtems_test_assert(*i == v);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, iz);
+    ++v;
+    rtems_test_assert(*i == v);
+
+    l = PER_CPU_DATA_GET(cpu, unsigned long, l);
+    ++v;
+    rtems_test_assert(*l == v);
+
+    l = PER_CPU_DATA_GET(cpu, unsigned long, lz);
+    ++v;
+    rtems_test_assert(*l == v);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, a[0]);
+    ++v;
+    rtems_test_assert(i[0] == v);
+    ++v;
+    rtems_test_assert(i[1] == v);
+    ++v;
+    rtems_test_assert(i[2] == v);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, az[0]);
+    ++v;
+    rtems_test_assert(i[0] == v);
+    ++v;
+    rtems_test_assert(i[1] == v);
+    ++v;
+    rtems_test_assert(i[2] == v);
+
+    pt = PER_CPU_DATA_GET(cpu, t, t);
+    ++v;
+    rtems_test_assert(pt->a == v);
+    ++v;
+    rtems_test_assert(pt->b == v);
+    ++v;
+    rtems_test_assert(pt->c == v);
+
+    i = PER_CPU_DATA_GET(cpu, unsigned int, g);
+    ++v;
+    rtems_test_assert(*i == v);
+  }
+}
+
+static void Init(rtems_task_argument arg)
+{
+  TEST_BEGIN();
+  test_initial_values();
+  set_unique_values(12);
+  test_unique_values(12);
+  TEST_END();
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_MAXIMUM_PROCESSORS 32
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/sppercpudata01/item.c b/testsuites/sptests/sppercpudata01/item.c
new file mode 100644
index 0000000000..2c29449a28
--- /dev/null
+++ b/testsuites/sptests/sppercpudata01/item.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sppercpudata01.h"
+
+PER_CPU_DATA_ITEM(unsigned int, g) = 11;
diff --git a/testsuites/sptests/sppercpudata01/sppercpudata01.doc b/testsuites/sptests/sppercpudata01/sppercpudata01.doc
new file mode 100644
index 0000000000..6ad5546ba8
--- /dev/null
+++ b/testsuites/sptests/sppercpudata01/sppercpudata01.doc
@@ -0,0 +1,13 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smppercpudata01
+
+directives:
+
+  - PER_CPU_DATA_ITEM_DECLARE()
+  - PER_CPU_DATA_ITEM()
+  - PER_CPU_DATA_GET()
+
+concepts:
+
+  - Ensure that the flexible per-CPU data works.
diff --git a/testsuites/sptests/sppercpudata01/sppercpudata01.h b/testsuites/sptests/sppercpudata01/sppercpudata01.h
new file mode 100644
index 0000000000..efed3cf5f5
--- /dev/null
+++ b/testsuites/sptests/sppercpudata01/sppercpudata01.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef SPPERCPUDATA01_H
+#define SPPERCPUDATA01_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <rtems/score/percpudata.h>
+
+PER_CPU_DATA_ITEM_DECLARE(unsigned int, g);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SPPERCPUDATA01_H */
diff --git a/testsuites/sptests/sppercpudata01/sppercpudata01.scn b/testsuites/sptests/sppercpudata01/sppercpudata01.scn
new file mode 100644
index 0000000000..15516a5e21
--- /dev/null
+++ b/testsuites/sptests/sppercpudata01/sppercpudata01.scn
@@ -0,0 +1,7 @@
+*** BEGIN OF TEST SMPPERCPUDATA 1 ***
+*** TEST VERSION: 5.0.0.6d70a1190539ade3f6ec67358461292908473066
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: RTEMS_SMP
+*** TEST TOOLS: 7.3.0 20180125 (RTEMS 5, RSB 02302026ccc257ece411d955836a3ac9b8afb9dc, Newlib d13c84eb07e35984bf7a974cd786a6cdac29e6b9)
+
+*** END OF TEST SMPPERCPUDATA 1 ***
-- 
2.13.7



More information about the devel mailing list