summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-06 13:50:16 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-06 13:50:16 +0200
commitd7e68c96b46599c7f3277d04ec4d1107ac2ff594 (patch)
treebb3a1273e8eca5d87b81381d606b56a590be1f95 /cpukit/libcsupport
parentscore: Delete _Chain_Append() (diff)
downloadrtems-d7e68c96b46599c7f3277d04ec4d1107ac2ff594.tar.bz2
malloc: Fix early realloc() allocation
Diffstat (limited to 'cpukit/libcsupport')
-rw-r--r--cpukit/libcsupport/src/malloc_deferred.c2
-rw-r--r--cpukit/libcsupport/src/malloc_p.h2
-rw-r--r--cpukit/libcsupport/src/realloc.c93
3 files changed, 51 insertions, 46 deletions
diff --git a/cpukit/libcsupport/src/malloc_deferred.c b/cpukit/libcsupport/src/malloc_deferred.c
index 2a4f5c892b..977ec7b3f6 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 127f22bac4..f3715a9966 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 6efdfdfdb8..7912780c09 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