[rtems commit] malloc: Add _Malloc_System_state()

Sebastian Huber sebh at rtems.org
Thu Feb 25 10:55:09 UTC 2016


Module:    rtems
Branch:    master
Commit:    9d1f39434585e8d3f8897d95a2bfe1ddccb79aec
Changeset: http://git.rtems.org/rtems/commit/?id=9d1f39434585e8d3f8897d95a2bfe1ddccb79aec

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Feb 25 09:02:43 2016 +0100

malloc: Add _Malloc_System_state()

Replace malloc_is_system_state_OK() with _Malloc_System_state() to allow
early allocations, e.g. in bsp_start().  Here the _Thread_Executing is
NULL, thus an _API_Mutex_Lock() would lead to a NULL pointer access.

Move malloc() support code to general case
rtems_heap_allocate_aligned_with_boundary().  Use
rtems_heap_allocate_aligned_with_boundary() to avoid duplicated code.

---

 cpukit/libcsupport/Makefile.am           |  2 +-
 cpukit/libcsupport/src/free.c            |  8 +---
 cpukit/libcsupport/src/malloc.c          | 33 ++--------------
 cpukit/libcsupport/src/malloc_deferred.c | 68 +++++++++++++++++++++++++++++---
 cpukit/libcsupport/src/malloc_p.h        | 15 ++++---
 cpukit/libcsupport/src/rtems_malloc.c    | 51 ------------------------
 cpukit/libcsupport/src/rtems_memalign.c  | 17 +-------
 testsuites/libtests/malloctest/init.c    | 27 ++++++++++++-
 8 files changed, 105 insertions(+), 116 deletions(-)

diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 0b2607f..eee9da7 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -87,7 +87,7 @@ MALLOC_C_FILES = src/malloc_initialize.c src/malloc.c \
     src/mallocinfo.c src/malloc_walk.c \
     src/posix_memalign.c \
     src/rtems_memalign.c src/malloc_deferred.c \
-    src/malloc_dirtier.c src/malloc_p.h src/rtems_malloc.c \
+    src/malloc_dirtier.c src/malloc_p.h \
     src/rtems_heap_extend_via_sbrk.c \
     src/rtems_heap_null_extend.c \
     src/rtems_heap_extend.c \
diff --git a/cpukit/libcsupport/src/free.c b/cpukit/libcsupport/src/free.c
index 63eb7b8..f3d4cb8 100644
--- a/cpukit/libcsupport/src/free.c
+++ b/cpukit/libcsupport/src/free.c
@@ -22,10 +22,6 @@
 #include "malloc_p.h"
 #include <stdlib.h>
 
-#include <rtems/score/sysstate.h>
-
-#include "malloc_p.h"
-
 void free(
   void *ptr
 )
@@ -36,8 +32,8 @@ void free(
   /*
    *  Do not attempt to free memory if in a critical section or ISR.
    */
-  if ( !malloc_is_system_state_OK() ) {
-      malloc_deferred_free(ptr);
+  if ( _Malloc_System_state() != MALLOC_SYSTEM_STATE_NORMAL ) {
+      _Malloc_Deferred_free(ptr);
       return;
   }
 
diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c
index 73203e5..03e2208 100644
--- a/cpukit/libcsupport/src/malloc.c
+++ b/cpukit/libcsupport/src/malloc.c
@@ -31,44 +31,17 @@ void *malloc(
   void        *return_this;
 
   /*
-   *  If some free's have been deferred, then do them now.
-   */
-  malloc_deferred_frees_process();
-
-  /*
    * Validate the parameters
    */
   if ( !size )
     return (void *) 0;
 
-  /*
-   *  Do not attempt to allocate memory if not in correct system state.
-   */
-  if ( !malloc_is_system_state_OK() )
-    return NULL;
-
-  /*
-   * Try to give a segment in the current heap if there is not
-   * enough space then try to grow the heap.
-   * If this fails then return a NULL pointer.
-   */
-
-  return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size );
-
+  return_this = rtems_heap_allocate_aligned_with_boundary( size, 0, 0 );
   if ( !return_this ) {
-    return_this = (*rtems_malloc_extend_handler)( RTEMS_Malloc_Heap, size );
-    if ( !return_this ) {
-      errno = ENOMEM;
-      return (void *) 0;
-    }
+    errno = ENOMEM;
+    return (void *) 0;
   }
 
-  /*
-   *  If the user wants us to dirty the allocated memory, then do it.
-   */
-  if ( rtems_malloc_dirty_helper )
-    (*rtems_malloc_dirty_helper)( return_this, size );
-
   return return_this;
 }
 
diff --git a/cpukit/libcsupport/src/malloc_deferred.c b/cpukit/libcsupport/src/malloc_deferred.c
index 395ed64..e781a05 100644
--- a/cpukit/libcsupport/src/malloc_deferred.c
+++ b/cpukit/libcsupport/src/malloc_deferred.c
@@ -34,10 +34,21 @@ static RTEMS_CHAIN_DEFINE_EMPTY( _Malloc_GC_list );
 
 RTEMS_INTERRUPT_LOCK_DEFINE( static, _Malloc_GC_lock, "Malloc GC" )
 
-bool malloc_is_system_state_OK(void)
+Malloc_System_state _Malloc_System_state( void )
 {
-  return !_System_state_Is_up( _System_state_Get() )
-    || _Thread_Dispatch_is_enabled();
+  System_state_Codes state = _System_state_Get();
+
+  if ( _System_state_Is_up( state ) ) {
+    if ( _Thread_Dispatch_is_enabled() ) {
+      return MALLOC_SYSTEM_STATE_NORMAL;
+    } else {
+      return MALLOC_SYSTEM_STATE_NO_ALLOCATION;
+    }
+  } else if ( _System_state_Is_before_multitasking( state ) ) {
+    return MALLOC_SYSTEM_STATE_NORMAL;
+  } else {
+    return MALLOC_SYSTEM_STATE_NO_PROTECTION;
+  }
 }
 
 static void *_Malloc_Get_deferred_free( void )
@@ -52,7 +63,7 @@ static void *_Malloc_Get_deferred_free( void )
   return p;
 }
 
-void malloc_deferred_frees_process( void )
+static void _Malloc_Process_deferred_frees( void )
 {
   rtems_chain_node *to_be_freed;
 
@@ -64,7 +75,54 @@ void malloc_deferred_frees_process( void )
   }
 }
 
-void malloc_deferred_free( void *p )
+void *rtems_heap_allocate_aligned_with_boundary(
+  uintptr_t size,
+  uintptr_t alignment,
+  uintptr_t boundary
+)
+{
+  Heap_Control *heap = RTEMS_Malloc_Heap;
+  void *p;
+
+  switch ( _Malloc_System_state() ) {
+    case MALLOC_SYSTEM_STATE_NORMAL:
+      _Malloc_Process_deferred_frees();
+      p = _Protected_heap_Allocate_aligned_with_boundary(
+        heap,
+        size,
+        alignment,
+        boundary
+      );
+      break;
+    case MALLOC_SYSTEM_STATE_NO_PROTECTION:
+      p = _Heap_Allocate_aligned_with_boundary(
+        heap,
+        size,
+        alignment,
+        boundary
+      );
+      break;
+    default:
+      /*
+       *  Do not attempt to allocate memory if not in correct system state.
+       */
+      return NULL;
+  }
+
+  if ( p == NULL && alignment == 0 && boundary == 0 ) {
+    p = (*rtems_malloc_extend_handler)( heap, size );
+  }
+
+  /*
+   *  If the user wants us to dirty the allocated memory, then do it.
+   */
+  if ( p != NULL && rtems_malloc_dirty_helper != NULL )
+    (*rtems_malloc_dirty_helper)( p, size );
+
+  return p;
+}
+
+void _Malloc_Deferred_free( void *p )
 {
   rtems_interrupt_lock_context lock_context;
 
diff --git a/cpukit/libcsupport/src/malloc_p.h b/cpukit/libcsupport/src/malloc_p.h
index 6609526..127f22b 100644
--- a/cpukit/libcsupport/src/malloc_p.h
+++ b/cpukit/libcsupport/src/malloc_p.h
@@ -17,12 +17,15 @@
 extern "C" {
 #endif /* __cplusplus */
 
-/*
- *  Process deferred free operations
- */
-bool malloc_is_system_state_OK(void);
-void malloc_deferred_frees_process(void);
-void malloc_deferred_free(void *);
+typedef enum {
+  MALLOC_SYSTEM_STATE_NORMAL,
+  MALLOC_SYSTEM_STATE_NO_PROTECTION,
+  MALLOC_SYSTEM_STATE_NO_ALLOCATION
+} Malloc_System_state;
+
+Malloc_System_state _Malloc_System_state( void );
+
+void _Malloc_Deferred_free( void * );
 
 #ifdef __cplusplus
 }
diff --git a/cpukit/libcsupport/src/rtems_malloc.c b/cpukit/libcsupport/src/rtems_malloc.c
deleted file mode 100644
index 9eaa1df..0000000
--- a/cpukit/libcsupport/src/rtems_malloc.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * @file
- *
- * @ingroup libcsupport
- *
- * @brief rtems_malloc() implementation.
- */
-
-/*
- * Copyright (c) 2009
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * D-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
-
-#ifdef RTEMS_NEWLIB
-#include "malloc_p.h"
-
-void *rtems_heap_allocate_aligned_with_boundary(
-  size_t size,
-  uintptr_t alignment,
-  uintptr_t boundary
-)
-{
-  if ( !malloc_is_system_state_OK() ) {
-    return NULL;
-  }
-
-  malloc_deferred_frees_process();
-
-  /* FIXME: Statistics, boundary checks */
-
-  return _Protected_heap_Allocate_aligned_with_boundary(
-    RTEMS_Malloc_Heap,
-    size,
-    alignment,
-    boundary
-  );
-}
-
-#endif
diff --git a/cpukit/libcsupport/src/rtems_memalign.c b/cpukit/libcsupport/src/rtems_memalign.c
index 5755fa0..8e3363e 100644
--- a/cpukit/libcsupport/src/rtems_memalign.c
+++ b/cpukit/libcsupport/src/rtems_memalign.c
@@ -41,24 +41,9 @@ int rtems_memalign(
   *pointer = NULL;
 
   /*
-   *  Do not attempt to allocate memory if not in correct system state.
-   */
-  if ( !malloc_is_system_state_OK() )
-    return EINVAL;
-
-  /*
-   *  If some free's have been deferred, then do them now.
-   */
-  malloc_deferred_frees_process();
-
-  /*
    *  Perform the aligned allocation requested
    */
-  return_this = _Protected_heap_Allocate_aligned(
-    RTEMS_Malloc_Heap,
-    size,
-    alignment
-  );
+  return_this = rtems_heap_allocate_aligned_with_boundary( size, alignment, 0 );
   if ( !return_this )
     return ENOMEM;
 
diff --git a/testsuites/libtests/malloctest/init.c b/testsuites/libtests/malloctest/init.c
index 7e1728d..acf25d7 100644
--- a/testsuites/libtests/malloctest/init.c
+++ b/testsuites/libtests/malloctest/init.c
@@ -2,7 +2,7 @@
  *  COPYRIGHT (c) 1989-2011, 2014.
  *  On-Line Applications Research Corporation (OAR).
  *
- *  Copyright (c) 2009, 2010 embedded brains GmbH.
+ *  Copyright (c) 2009, 2016 embedded brains GmbH.
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <rtems/score/protectedheap.h>
 #include <rtems/malloc.h>
+#include <rtems/sysinit.h>
 
 const char rtems_test_name[] = "MALLOCTEST";
 
@@ -1369,3 +1370,27 @@ rtems_task Init(
   status = rtems_task_delete( RTEMS_SELF );
   directive_failed( status, "rtems_task_delete of RTEMS_SELF" );
 }
+
+static void test_early_malloc( void )
+{
+  void *p;
+  char *q;
+
+  p = malloc( 1 );
+  rtems_test_assert( p != NULL );
+
+  free( p );
+
+  q = calloc( 1, 1 );
+  rtems_test_assert( q != NULL );
+  rtems_test_assert( p != q );
+  rtems_test_assert( q[0] == 0 );
+
+  free( q );
+}
+
+RTEMS_SYSINIT_ITEM(
+  test_early_malloc,
+  RTEMS_SYSINIT_INITIAL_EXTENSIONS,
+  RTEMS_SYSINIT_ORDER_FIRST
+);




More information about the vc mailing list