This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] ARM semihosted heap limits


The ARM semihosting syscalls (as used by the default arm-none-eabi newlib 
configuration) provide a mechanism for the host to inform the program of the 
heap memory area.

Currently newlib ignores these, and uses the area between the end of the data 
segment and the stack.

The patch below makes the _sbrk implementation honour these values, and 
gracefully fall back to the old behaviour is they are not 
available/specified.

Tested on arm-none-eabi with a variety of semihosting implementations.
Ok?

Paul

2007-04-05  Paul Brook  <paul@codesourcery.com>

	libgloss/
	* arm/crt0.S: Define __heap_base__ and __heap_limit__.
	* arm/syscalls.c (_sbrk): Use them.

	newlib/
	* libc/sys/arm/crt0.S: Define __heap_base__ and __heap_limit__.
	* libc/sys/arm/syscalls.c (_sbrk): Use them.
Index: libgloss/arm/crt0.S
===================================================================
RCS file: /var/cvsroot/src-cvs/src/libgloss/arm/crt0.S,v
retrieving revision 1.5
diff -u -p -r1.5 crt0.S
--- libgloss/arm/crt0.S	7 Feb 2006 18:46:23 -0000	1.5
+++ libgloss/arm/crt0.S	5 Apr 2007 18:03:26 -0000
@@ -325,7 +325,7 @@ change_back:
 	.align 0
 .LC0:
 #ifdef ARM_RDI_MONITOR
-	.word	HeapBase
+	.word	__heap_base__
 #else
 #ifndef ARM_RDP_MONITOR
 	/* Changes by toralf: Provide alternative "stack" variable whose value
@@ -384,8 +384,10 @@ change_back:
 	.data
 /*  Data returned by monitor SWI.  */
 .global	__stack_base__
-HeapBase:	.word	0
-HeapLimit:	.word	0
+.global __heap_base__
+.global __heap_limit__
+__heap_base__:	.word	0
+__heap_limit__:	.word	0
 __stack_base__:	.word	0
 StackLimit:	.word	0
 CommandLine:	.space	256,0	/*  Maximum length of 255 chars handled.  */
Index: libgloss/arm/syscalls.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/libgloss/arm/syscalls.c,v
retrieving revision 1.14
diff -u -p -r1.14 syscalls.c
--- libgloss/arm/syscalls.c	3 Jan 2007 16:55:25 -0000	1.14
+++ libgloss/arm/syscalls.c	5 Apr 2007 18:10:42 -0000
@@ -443,19 +443,36 @@ _getpid (int n)
   n = n;
 }
 
+extern char * __heap_limit__ __attribute__((weak));
+extern char * __heap_base__ __attribute__((weak));
+
 caddr_t
 _sbrk (int incr)
 {
   extern char   end asm ("end");	/* Defined by the linker.  */
   static char * heap_end;
+  static char * heap_base;
   char *        prev_heap_end;
 
-  if (heap_end == NULL)
-    heap_end = & end;
-  
+  if (heap_base == NULL)
+    {
+      /* If no heap base is provided then start from the end of the
+         data segment.  */
+      if (&__heap_base__ && __heap_base__)
+	heap_base = __heap_base__;
+      else
+	heap_base = &end;
+      heap_end = heap_base;
+    }
+
   prev_heap_end = heap_end;
-  
-  if (heap_end + incr > stack_ptr)
+
+  /* Check if we will run over into the stack, or if we exceed a specified
+     heap limit.  Avoid errors in the case where the heap is entirely above
+     the stack.  */
+  if ((heap_base < stack_ptr && heap_end + incr > stack_ptr)
+      || (&__heap_limit__ && __heap_limit__
+	  && heap_end + incr > __heap_limit__))
     {
       /* Some of the libstdc++-v3 tests rely upon detecting
 	 out of memory errors, so do not abort here.  */
Index: newlib/libc/sys/arm/crt0.S
===================================================================
RCS file: /var/cvsroot/src-cvs/src/newlib/libc/sys/arm/crt0.S,v
retrieving revision 1.12
diff -u -p -r1.12 crt0.S
--- newlib/libc/sys/arm/crt0.S	7 Feb 2006 18:44:54 -0000	1.12
+++ newlib/libc/sys/arm/crt0.S	5 Apr 2007 18:12:13 -0000
@@ -260,7 +260,7 @@ change_back:
 	.align 0
 .LC0:
 #ifdef ARM_RDI_MONITOR
-	.word	HeapBase
+	.word	__heap_base__
 #else
 #ifndef ARM_RDP_MONITOR
 #ifdef __pe__
@@ -292,8 +292,10 @@ change_back:
 	.data
 /*  Data returned by monitor SWI.  */
 .global	__stack_base__
-HeapBase:	.word	0
-HeapLimit:	.word	0
+.global __heap_base__
+.global __heap_limit__
+__heap_base__:	.word	0
+__heap_limit__:	.word	0
 __stack_base__:	.word	0
 StackLimit:	.word	0
 CommandLine:	.space	256,0	/*  Maximum length of 255 chars handled.  */
Index: newlib/libc/sys/arm/syscalls.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/newlib/libc/sys/arm/syscalls.c,v
retrieving revision 1.13
diff -u -p -r1.13 syscalls.c
--- newlib/libc/sys/arm/syscalls.c	13 Jun 2006 20:50:24 -0000	1.13
+++ newlib/libc/sys/arm/syscalls.c	5 Apr 2007 18:12:13 -0000
@@ -472,19 +472,36 @@ _getpid (int n)
   n = n;
 }
 
+extern char * __heap_limit__ __attribute__((weak));
+extern char * __heap_base__ __attribute__((weak));
+
 caddr_t
 _sbrk (int incr)
 {
   extern char   end asm ("end");	/* Defined by the linker.  */
   static char * heap_end;
+  static char * heap_base;
   char *        prev_heap_end;
 
-  if (heap_end == NULL)
-    heap_end = & end;
-  
+  if (heap_base == NULL)
+    {
+      /* If no heap base is provided then start from the end of the
+         data segment.  */
+      if (&__heap_base__ && __heap_base__)
+	heap_base = __heap_base__;
+      else
+	heap_base = &end;
+      heap_end = heap_base;
+    }
+
   prev_heap_end = heap_end;
-  
-  if (heap_end + incr > stack_ptr)
+
+  /* Check if we will run over into the stack, or if we exceed a specified
+     heap limit.  Avoid errors in the case where the heap is entirely above
+     the stack.  */
+  if ((heap_base < stack_ptr && heap_end + incr > stack_ptr)
+      || (&__heap_limit__ && __heap_limit__
+	  && heap_end + incr > __heap_limit__))
     {
       /* Some of the libstdc++-v3 tests rely upon detecting
 	 out of memory errors, so do not abort here.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]