[rtems commit] malloc: Fix early realloc() allocation

Sebastian Huber sebh at rtems.org
Wed Apr 6 11:54:27 UTC 2016


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Apr  6 13:50:16 2016 +0200

malloc: Fix early realloc() allocation

---

 cpukit/libcsupport/src/malloc_deferred.c |  2 +-
 cpukit/libcsupport/src/malloc_p.h        |  2 +
 cpukit/libcsupport/src/realloc.c         | 93 ++++++++++++++++----------------
 testsuites/libtests/malloctest/init.c    | 17 ++++++
 4 files changed, 68 insertions(+), 46 deletions(-)

diff --git a/cpukit/libcsupport/src/malloc_deferred.c b/cpukit/libcsupport/src/malloc_deferred.c
index 2a4f5c8..977ec7b 100644
--- a/cpukit/libcsupport/src/malloc_deferred.c
+++ b/cpukit/libcsupport/src/malloc_deferred.c
@@ -63,7 +63,7 @@ static void *_Malloc_Get_deferred_free( void )
   return p;
 }
 
-static void _Malloc_Process_deferred_frees( void )
+void _Malloc_Process_deferred_frees( void )
 {
   rtems_chain_node *to_be_freed;
 
diff --git a/cpukit/libcsupport/src/malloc_p.h b/cpukit/libcsupport/src/malloc_p.h
index 127f22b..f3715a9 100644
--- a/cpukit/libcsupport/src/malloc_p.h
+++ b/cpukit/libcsupport/src/malloc_p.h
@@ -27,6 +27,8 @@ Malloc_System_state _Malloc_System_state( void );
 
 void _Malloc_Deferred_free( void * );
 
+void _Malloc_Process_deferred_frees( void );
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/cpukit/libcsupport/src/realloc.c b/cpukit/libcsupport/src/realloc.c
index 6efdfdf..7912780 100644
--- a/cpukit/libcsupport/src/realloc.c
+++ b/cpukit/libcsupport/src/realloc.c
@@ -19,70 +19,73 @@
 #endif
 
 #ifdef RTEMS_NEWLIB
-#include "malloc_p.h"
-#include <stdlib.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 
-#include <rtems/score/sysstate.h>
-#include <rtems/score/objectimpl.h>
+#include "malloc_p.h"
 
-void *realloc(
-  void *ptr,
-  size_t size
-)
+static void *new_alloc( void *old_ptr, size_t new_size, size_t old_size )
 {
-  uintptr_t old_size;
-  char    *new_area;
+  void *new_ptr;
 
   /*
-   *  Do not attempt to allocate memory if in a critical section or ISR.
+   *  There used to be a free on this error case but it is wrong to
+   *  free the memory per OpenGroup Single UNIX Specification V2
+   *  and the C Standard.
    */
 
-  if (_System_state_Is_up(_System_state_Get())) {
-    if (!_Thread_Dispatch_is_enabled())
-      return (void *) 0;
+  new_ptr = malloc( new_size );
+  if ( new_ptr == NULL ) {
+    return NULL;
   }
 
-  /*
-   * Continue with realloc().
-   */
-  if ( !ptr )
-    return malloc( size );
+  memcpy( new_ptr, old_ptr, ( new_size < old_size ) ? new_size : old_size );
+  free( old_ptr );
+
+  return new_ptr;
+}
+
+void *realloc( void *ptr, size_t size )
+{
+  Heap_Control       *heap;
+  Heap_Resize_status  status;
+  uintptr_t           old_size;
+  uintptr_t           avail_size;
 
-  if ( !size ) {
+  if ( size == 0 ) {
     free( ptr );
-    return (void *) 0;
+    return NULL;
   }
 
-  if ( !_Protected_heap_Get_block_size(RTEMS_Malloc_Heap, ptr, &old_size) ) {
-    errno = EINVAL;
-    return (void *) 0;
+  if ( ptr == NULL ) {
+    return malloc( size );
   }
 
-  /*
-   *  Now resize it.
-   */
-  if ( _Protected_heap_Resize_block( RTEMS_Malloc_Heap, ptr, size ) ) {
-    return ptr;
+  heap = RTEMS_Malloc_Heap;
+
+  switch ( _Malloc_System_state() ) {
+    case MALLOC_SYSTEM_STATE_NORMAL:
+      _RTEMS_Lock_allocator();
+      _Malloc_Process_deferred_frees();
+      status = _Heap_Resize_block( heap, ptr, size, &old_size, &avail_size );
+      _RTEMS_Unlock_allocator();
+      break;
+    case MALLOC_SYSTEM_STATE_NO_PROTECTION:
+      status = _Heap_Resize_block( heap, ptr, size, &old_size, &avail_size );
+      break;
+    default:
+      return NULL;
   }
 
-  /*
-   *  There used to be a free on this error case but it is wrong to
-   *  free the memory per OpenGroup Single UNIX Specification V2
-   *  and the C Standard.
-   */
-
-  new_area = malloc( size );
-
-  if ( !new_area ) {
-    return (void *) 0;
+  switch ( status ) {
+    case HEAP_RESIZE_SUCCESSFUL:
+      return ptr;
+    case HEAP_RESIZE_UNSATISFIED:
+      return new_alloc( ptr, size, old_size );
+    default:
+      errno = EINVAL;
+      return NULL;
   }
-
-  memcpy( new_area, ptr, (size < old_size) ? size : old_size );
-  free( ptr );
-
-  return new_area;
-
 }
 #endif
diff --git a/testsuites/libtests/malloctest/init.c b/testsuites/libtests/malloctest/init.c
index acf25d7..6123977 100644
--- a/testsuites/libtests/malloctest/init.c
+++ b/testsuites/libtests/malloctest/init.c
@@ -1375,6 +1375,9 @@ static void test_early_malloc( void )
 {
   void *p;
   char *q;
+  void *r;
+  void *s;
+  void *t;
 
   p = malloc( 1 );
   rtems_test_assert( p != NULL );
@@ -1387,6 +1390,20 @@ static void test_early_malloc( void )
   rtems_test_assert( q[0] == 0 );
 
   free( q );
+
+  r = realloc( q, 128 );
+  rtems_test_assert( r == q );
+
+  s = malloc( 1 );
+  rtems_test_assert( s != NULL );
+
+  free( s );
+
+  t = realloc( r, 256 );
+  rtems_test_assert( t != NULL );
+  rtems_test_assert( t != r );
+
+  free( t );
 }
 
 RTEMS_SYSINIT_ITEM(




More information about the vc mailing list