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]

Re: Weird behavior of mallocr() function


On 05/01/10 03:39 AM, Denis Micolani wrote:
For starters, your linker script is restricting the heap to be 0x400 bytes
(1024).  That is less that 1344 so your return code makes sense. Malloc
creates bins to reuse for small allocations so if you are really this
constrained for space, you won't be able to use the malloc logic in newlib
and will have to override it.

It seems kinda weird to me that malloc is asking an allocation for about 1.34Kbytes while I'm just asking for 1 byte. Anyway if that's the way it works, I got nothing to complain about, I'll just expand the heap area in the linker script to be a bit larger.


The algorithm is trying to balance speed and storage usage as well as minimize fragmentation. The point of the fixed-size bins is that when you ask for small amounts of storage, it doesn't go to the external pool. Instead, it has a reusable set of slots that can be quickly accessed/reused and it doesn't have to waste bytes on overhead (slot is free or taken which can be tracked with a single bit). Imagine if you instead always called sbrk for storage and asked for 1000 bytes then 1 byte, then another 1000. If you free both of the 1000 byte blocks, you can't reclaim the 2000+ bytes together until the 1 byte block is freed. The one byte block here is actually taking up more space due to the overhead of keeping track of it. If you free n 1 byte blocks in a row, combining them together still doesn't net you much. If the really small stuff is kept off in the bins, everything left is worth recombining after freeing to get larger areas.



As well, your current code isn't going to work.  You are adding incr to
heap_start and comparing this to heap_end (i.e. neither changes).  I'm
pretty sure you meant to use heap_current_end in your if statement.
As well, if you are going to have a reentrant version, you might as well set
errno properly using the reentrant struct that is input.
See newlib/libc/include/sys/errno.h for the __errno_r macro.

Thanks for pointing that out!



Most sbrk implementations use the logic found in libgloss/libnosys/sbrk.c
which has the heap and stack going in opposite directions and allocates a
lump sum for the two in the linker script. This allows peaks for either the
stack or heap as long as the total is within limits.  You might want to
check out this design before implementing your own.

I did not realize there were such a directory with all those useful functions within, thanks for pointing this out too!


Just one more question: AFAIK, in order to get malloc to be reentrant, I should provide my own stubs to lock and unlock the memory, these should be: __malloc_unlock() and __malloc_lock(). Anyway if I define them just like other stubs in the global scope I get the compiler to fail, saying that there are multiple definitions of those. Specifically, saying that they were already defined in newlib-1.18.0/newlib/libc/stdlib/mlock.c .So, how could I manage to get it to work? Should I place my own stub directly in newlib's source code and recompile it (it doesn't seem to me like a good idea) ?

Normally, a platform has its own libc/machine subdirectory. Files there are used to override the ones in the shared directories of newlib. For example, if you have a libc/machine/XXX directory and put your own mlock.c file there, it will override the one in stdlib (where XXX is the name of your platform). There are plenty of examples in the newlib repository under libc/machine. You have to specify this in configure.host. There are instructions on the newlib web-site in the FAQ section.


-- Jeff J.


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