[PATCH 1/2] rtems: Add rtems_cache_coherent_allocate()

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Nov 25 16:28:41 UTC 2014


Add rtems_cache_coherent_free() and rtems_cache_coherent_add_area().
---
 cpukit/libcsupport/Makefile.am              |   1 +
 cpukit/libcsupport/src/cachecoherentalloc.c | 122 ++++++++++++++++++++++++++++
 cpukit/rtems/include/rtems/rtems/cache.h    |  61 ++++++++++++++
 testsuites/sptests/spcache01/init.c         |  47 +++++++++++
 testsuites/sptests/spcache01/spcache01.doc  |   3 +
 testsuites/sptests/spcache01/spcache01.scn  |   1 +
 6 files changed, 235 insertions(+)
 create mode 100644 cpukit/libcsupport/src/cachecoherentalloc.c

diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 95c85c4..dfa8736 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -109,6 +109,7 @@ MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \
     src/rtems_heap_extend.c \
     src/rtems_heap_greedy.c
 MALLOC_C_FILES += src/cachealignedalloc.c
+MALLOC_C_FILES += src/cachecoherentalloc.c
 
 PASSWORD_GROUP_C_FILES = src/pwdgrp.c
 PASSWORD_GROUP_C_FILES += src/getgrent.c
diff --git a/cpukit/libcsupport/src/cachecoherentalloc.c b/cpukit/libcsupport/src/cachecoherentalloc.c
new file mode 100644
index 0000000..bf8167d
--- /dev/null
+++ b/cpukit/libcsupport/src/cachecoherentalloc.c
@@ -0,0 +1,122 @@
+/**
+ * @file
+ *
+ * @ingroup ClassicCache
+ */
+
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#if HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include <rtems/score/apimutex.h>
+#include <rtems/score/heapimpl.h>
+#include <rtems/score/sysstate.h>
+
+static Heap_Control cache_coherent_heap_instance;
+
+static Heap_Control *cache_coherent_heap;
+
+void *rtems_cache_coherent_allocate(
+  size_t size,
+  uintptr_t alignment,
+  uintptr_t boundary
+)
+{
+  void *ptr;
+  Heap_Control *heap;
+
+  _RTEMS_Lock_allocator();
+
+  heap = cache_coherent_heap;
+  if ( heap == NULL ) {
+    heap = RTEMS_Malloc_Heap;
+  }
+
+  ptr = _Heap_Allocate_aligned_with_boundary(
+    heap,
+    size,
+    alignment,
+    boundary
+  );
+
+  _RTEMS_Unlock_allocator();
+
+  return ptr;
+}
+
+void rtems_cache_coherent_free( void *ptr )
+{
+  Heap_Control *heap;
+
+  _RTEMS_Lock_allocator();
+
+  heap = cache_coherent_heap;
+  if ( heap != NULL ) {
+    if ( _Heap_Free( heap, ptr ) ) {
+      heap = NULL;
+    } else {
+      heap = RTEMS_Malloc_Heap;
+    }
+  } else {
+    heap = RTEMS_Malloc_Heap;
+  }
+
+  if ( heap != NULL ) {
+    _Heap_Free( heap, ptr );
+  }
+
+  _RTEMS_Unlock_allocator();
+}
+
+static void add_area(
+  void *area_begin,
+  uintptr_t area_size
+)
+{
+  Heap_Control *heap = cache_coherent_heap;
+
+  if ( heap == NULL ) {
+    bool ok;
+
+    heap = &cache_coherent_heap_instance;
+
+    ok = _Heap_Initialize( heap, area_begin, area_size, 0 );
+    if ( ok ) {
+      cache_coherent_heap = heap;
+    }
+  } else {
+    _Heap_Extend( heap, area_begin, area_size, 0 );
+  }
+}
+
+void rtems_cache_coherent_add_area(
+  void *area_begin,
+  uintptr_t area_size
+)
+{
+  if ( _System_state_Is_up( _System_state_Get()) ) {
+    _RTEMS_Lock_allocator();
+
+    add_area( area_begin, area_size );
+
+    _RTEMS_Unlock_allocator();
+  } else {
+    add_area( area_begin, area_size );
+  }
+}
diff --git a/cpukit/rtems/include/rtems/rtems/cache.h b/cpukit/rtems/include/rtems/rtems/cache.h
index ce399c6..a7dcaa6 100644
--- a/cpukit/rtems/include/rtems/rtems/cache.h
+++ b/cpukit/rtems/include/rtems/rtems/cache.h
@@ -191,6 +191,67 @@ void rtems_cache_disable_instruction( void );
  */
 void *rtems_cache_aligned_malloc ( size_t nbytes );
 
+/**
+ * @brief Allocates a memory area of size @a size bytes from cache coherent
+ * memory.
+ *
+ * A size value of zero will return a unique address which may be freed with
+ * rtems_cache_coherent_free().
+ *
+ * The memory allocated by this function can be released with a call to
+ * rtems_cache_coherent_free().
+ *
+ * By default the C program heap allocator is used.  In case special memory
+ * areas must be used, then the BSP or the application must add cache coherent
+ * memory areas for the allocator via rtems_cache_coherent_add_area().
+ *
+ * This function must be called from driver initialization or task context
+ * only.
+ *
+ * @param[in] alignment If the alignment parameter is not equal to zero, the
+ *   allocated memory area will begin at an address aligned by this value.
+ * @param[in] boundary If the boundary parameter is not equal to zero, the
+ *   allocated memory area will comply with a boundary constraint.  The
+ *   boundary value specifies the set of addresses which are aligned by the
+ *   boundary value.  The interior of the allocated memory area will not
+ *   contain an element of this set.  The begin or end address of the area may
+ *   be a member of the set.
+ *
+ * @retval NULL If no memory is available or the parameters are inconsistent.
+ * @retval other A pointer to the begin of the allocated memory area.
+ */
+void *rtems_cache_coherent_allocate(
+  size_t size,
+  uintptr_t alignment,
+  uintptr_t boundary
+);
+
+/**
+ * @brief Frees memory allocated by rtems_cache_coherent_allocate().
+ *
+ * This function must be called from driver initialization or task context
+ * only.
+ *
+ * @param[in] ptr A pointer returned by rtems_cache_coherent_allocate().
+ */
+void rtems_cache_coherent_free( void *ptr );
+
+/**
+ * @brief Adds a cache coherent memory area to the cache coherent allocator.
+ *
+ * This function must be called from BSP initialization, driver initialization
+ * or task context only.
+ *
+ * @param[in] area_begin The area begin address.
+ * @param[in] area_size The area size in bytes.
+ *
+ * @see rtems_cache_coherent_allocate().
+ */
+void rtems_cache_coherent_add_area(
+  void *area_begin,
+  uintptr_t area_size
+);
+
 #if defined( RTEMS_SMP )
 
 /**
diff --git a/testsuites/sptests/spcache01/init.c b/testsuites/sptests/spcache01/init.c
index 95777e1..8ed3dbe 100644
--- a/testsuites/sptests/spcache01/init.c
+++ b/testsuites/sptests/spcache01/init.c
@@ -22,6 +22,7 @@
 
 #include <rtems.h>
 #include <rtems/counter.h>
+#include <rtems/score/sysstate.h>
 
 #define TESTS_USE_PRINTF
 #include "tmacros.h"
@@ -409,6 +410,51 @@ static void test_cache_aligned_alloc(void)
   free(p1);
 }
 
+#define AREA_SIZE 256
+
+static char cache_coherent_area_0[AREA_SIZE];
+
+static char cache_coherent_area_1[AREA_SIZE];
+
+static char cache_coherent_area_2[AREA_SIZE];
+
+static void add_area(void *begin)
+{
+  rtems_cache_coherent_add_area(NULL, 0);
+  rtems_cache_coherent_add_area(begin, AREA_SIZE);
+}
+
+static void test_cache_coherent_alloc(void)
+{
+  void *p0;
+  void *p1;
+  System_state_Codes previous_state;
+
+  printf("test cache coherent allocation\n");
+
+  p0 = rtems_cache_coherent_allocate(1, 0, 0);
+  rtems_test_assert(p0 != NULL);
+
+  rtems_cache_coherent_free(p0);
+
+  p0 = rtems_cache_coherent_allocate(1, 0, 0);
+  rtems_test_assert(p0 != NULL);
+
+  add_area(&cache_coherent_area_0[0]);
+  add_area(&cache_coherent_area_1[0]);
+
+  previous_state = _System_state_Get();
+  _System_state_Set(previous_state + 1);
+  add_area(&cache_coherent_area_2[0]);
+  _System_state_Set(previous_state);
+
+  p1 = rtems_cache_coherent_allocate(1, 0, 0);
+  rtems_test_assert(p1 != NULL);
+
+  rtems_cache_coherent_free(p0);
+  rtems_cache_coherent_free(p1);
+}
+
 static void Init(rtems_task_argument arg)
 {
   TEST_BEGIN();
@@ -416,6 +462,7 @@ static void Init(rtems_task_argument arg)
   test_data_flush_and_invalidate();
   test_timing();
   test_cache_aligned_alloc();
+  test_cache_coherent_alloc();
 
   TEST_END();
 
diff --git a/testsuites/sptests/spcache01/spcache01.doc b/testsuites/sptests/spcache01/spcache01.doc
index 04e32a1..9c33d94 100644
--- a/testsuites/sptests/spcache01/spcache01.doc
+++ b/testsuites/sptests/spcache01/spcache01.doc
@@ -14,6 +14,9 @@ directives:
   - rtems_cache_invalidate_multiple_data_lines()
   - rtems_cache_invalidate_multiple_instruction_lines()
   - rtems_cache_aligned_malloc()
+  - rtems_cache_coherent_allocate()
+  - rtems_cache_coherent_free()
+  - rtems_cache_coherent_add_area()
 
 concepts:
 
diff --git a/testsuites/sptests/spcache01/spcache01.scn b/testsuites/sptests/spcache01/spcache01.scn
index 4e7d53a..6f1d2a6 100644
--- a/testsuites/sptests/spcache01/spcache01.scn
+++ b/testsuites/sptests/spcache01/spcache01.scn
@@ -43,4 +43,5 @@ invalidate multiple instruction
   duration with warm cache 640 ns
   duration with invalidated cache 2600 ns
 test rtems_cache_aligned_malloc()
+test cache coherent allocation
 *** END OF TEST SPCACHE 1 ***
-- 
1.8.4.5



More information about the devel mailing list