Difference between revisions of "How does Newlib initialize the heap?"
(Created page with "== '''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...") |
|||
Line 46: | Line 46: | ||
return (void *) prev_heap_end; | 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 initializes 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:''' | '''ARM:''' |
Revision as of 12:18, 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 initializes 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.