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

From GNU Tools - Wiki
Jump to: navigation, search
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
 
== '''How does Newlib initialize 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''', users 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:
+
Users of the '''Newlib-Nano Library''' must provide an implementation of the sbrk() function, since there is no default implementation included.
 
+
'''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:
 
Below are some examples of the default _sbrk function, depending on the toolchain used:

Latest revision as of 13:06, 13 January 2023

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

When using the Newlib Library, users 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.

Users of the Newlib-Nano Library must provide an implementation of the sbrk() function, since there is no default implementation included.

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.