Difference between revisions of "How does Newlib initialize the heap?"

From GNU Tools - Wiki
Jump to: navigation, search
Line 85: Line 85:
  
  
== '''How does Newlib initializes the heap? (RL78, RX, ARM targets)''' ==
+
== '''How does Newlib initialize the heap? (RL78, RX, ARM targets)''' ==
  
 
When using the '''Newlib Library''', the user must overwrite the _sbrk/sbrk_r function implemented in newlib. This is the function malloc() uses in order to define how much space is needed for an allocation.
 
When using the '''Newlib Library''', the user must overwrite the _sbrk/sbrk_r function implemented in newlib. This is the function malloc() uses in order to define how much space is needed for an allocation.

Revision as of 12:19, 31 May 2019

How does Newlib initialize the heap? (RL78, RX, ARM targets)

When using the Newlib Library, the user must overwrite the _sbrk/sbrk_r function implemented in newlib. This is the function malloc() uses in order to define how much space is needed for an allocation.

Below are some examples of the default _sbrk function, depending on the toolchain used:

RL78:

 char *
 _sbrk (int adj)
 {
   extern char    end; //end of the bss section (start of heap)
   static char *  heap = & end;
   char *         rv = heap;
   char *	 heaptop = (char *) &adj;
 
   heap += adj;
 
       /* The allocated chunk spans our stack?  */
  if (rv < heaptop && heap > heaptop
       /* The allocated chunk spans our address space?  */
       || heap < rv)
     {
       return (char *) -1;
     }
 
   return rv;
 }

RX:

 void*
 _sbrk (incr)
      int incr;
 {
    extern char   end; /* Set by linker.  */
    static char * heap_end;
    char *        prev_heap_end;
 
    if (heap_end == 0)
      heap_end = & end;
 
    prev_heap_end = heap_end;
    heap_end += incr;
 
    return (void *) prev_heap_end;
 }

ARM:

 register char * stack_ptr asm ("sp");
 caddr_t __attribute__((weak))
 _sbrk (int incr)
 {
   extern char   end asm ("end");	/* Defined by the linker.  */
   static char * heap_end;
   char *        prev_heap_end;
 
   if (heap_end == NULL)
     heap_end = & end;
   
   prev_heap_end = heap_end;
   
   if (heap_end + incr > stack_ptr)
     {
       /* Some of the libstdc++-v3 tests rely upon detecting
 	 out of memory errors, so do not abort here.  */
 #if 0
       extern void abort (void);
 
       _write (1, "_sbrk: Heap and stack collision\n", 32);
       
       abort ();
 #else
       errno = ENOMEM;
       return (caddr_t) -1;
 #endif
     }
   
   heap_end += incr;
 
   return (caddr_t) prev_heap_end;
 }

These are the functions to overwrite if there is a need to set your own heap.


How does Newlib initialize the heap? (RL78, RX, ARM targets)

When using the Newlib Library, the user must overwrite the _sbrk/sbrk_r function implemented in newlib. This is the function malloc() uses in order to define how much space is needed for an allocation.

Below are some examples of the default _sbrk function, depending on the toolchain used:

RL78:

 char *
 _sbrk (int adj)
 {
   extern char    end; //end of the bss section (start of heap)
   static char *  heap = & end;
   char *         rv = heap;
   char *	 heaptop = (char *) &adj;
 
   heap += adj;
 
       /* The allocated chunk spans our stack?  */
  if (rv < heaptop && heap > heaptop
       /* The allocated chunk spans our address space?  */
       || heap < rv)
     {
       errno = ENOMEM;
       return (char *) -1;
     }
 
   return rv;
 }

RX:

 extern void __set_heaptop (void * ptr);
 char *
 _sbrk (int adj)
 {
   extern char    end;
   static char *  heap = & end;
   char *         rv = heap;
 
   heap += adj;
   __set_heaptop (heap);
   return rv;
 }


ARM:

 register char * stack_ptr asm ("sp");
 caddr_t __attribute__((weak))
 _sbrk (int incr)
 {
   extern char   end asm ("end");	/* Defined by the linker.  */
   static char * heap_end;
   char *        prev_heap_end;
 
   if (heap_end == NULL)
     heap_end = & end;
   
   prev_heap_end = heap_end;
   
   if (heap_end + incr > stack_ptr)
     {
       /* Some of the libstdc++-v3 tests rely upon detecting
 	 out of memory errors, so do not abort here.  */
 #if 0
       extern void abort (void);
 
       _write (1, "_sbrk: Heap and stack collision\n", 32);
       
       abort ();
 #else
       errno = ENOMEM;
       return (caddr_t) -1;
 #endif
     }
   
   heap_end += incr;
 
   return (caddr_t) prev_heap_end;
 }

These are the functions to overwrite if there is a need to set your own heap.