oldlib/newlib heap initialisation

Post Reply
oPless
New member
Posts: 3
Joined: Fri Jul 12, 2019 11:45 pm

oldlib/newlib heap initialisation

Post by oPless »

Hi,

I've been struggling with finding out how newlib manages to determine the heapsize on CP/M.

I'm trying to replicate this function under the default library, as newlib has no file operations available.

I can statically define memory and initialize the allocator there.

I can roughly determine the top of the stack by grabbing the address of a local variable, and roughly the end of the bss, by grabbing the address of a global variable.

Neither are really good enough for picking up the because I don't know how big the stack section might be, nor the true size of the BSS.

I'm surprised the documentation which goes into detail about how to go about setting up using mallinit/sbrk, but misses out this.

So is there a way of determining the highest address of BSS, and the lowest part of the stack within C?
stefano
Well known member
Posts: 1534
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

I hope I understood your question correctly, it seems to me we can split the arguments in three: how to determine the free memory on a CP/M system I order to assign the segments to stack, bss, heap, etc.. the newlib or the libraries in general (file i/o) an the two malloc library variants.
Could you please clarify what you are willing to get ? I suppose you are using the clib=new flag, correct ?

EDIT: could the -DAMALLOC compiler option meet your needs?
oPless
New member
Posts: 3
Joined: Fri Jul 12, 2019 11:45 pm

Post by oPless »

stefano wrote:I hope I understood your question correctly, it seems to me we can split the arguments in three: how to determine the free memory on a CP/M system I order to assign the segments to stack, bss, heap, etc.. the newlib or the libraries in general (file i/o) an the two malloc library variants.
Could you please clarify what you are willing to get ? I suppose you are using the clib=new flag, correct ?

EDIT: could the -DAMALLOC compiler option meet your needs?
Hi Stefano!

I had been using clib=new, as it's new and shiny and has an out of the box working malloc.
Alas I had to revert to classic library, as newlib doesn't have file support.

newlib appears to sbrk around 50K to the heap
-DAMALLOC appears sbrk around 40K to the heap

Both running on the RunCPM emulator which is just fine.

***So yes, it appears that -DAMALLOC is exactly what I needed here***. Thank you.

....Though a bit more googling I see a '-pragma-define:USING_amalloc' I presume this is a more verbose or depricated way of saying the same thing?
stefano
Well known member
Posts: 1534
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

A bit more verbose one. AMALLOC is in most of the case little more than a trick setting the heap automatically at an average size.

We borrowed a good portion of the new lib bringing into the classic lib, but we rarely did the opposite. As far as I know the new lib is far more flexible on the way it deals with the file streams.

On the other side, the classic lib had a longer life and few more tricks developed on it (e.g. the user specified file redirection on the command line).
User avatar
dom
Well known member
Posts: 1194
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

As Stefano has indicated, there's been a consolidation of library code, with classic taking much of the standard library (and newlib algorithms etc), there's an intro to classic on this page: https://github.com/z88dk/z88dk/wiki/Classic-Overview

From the viewpoint of CP/M the only real difference will be in stdio and fileio, there's some upcoming work which should also allow classic to work on 8080 based CP/M machines (albeit with some limitations).

To come back to your original question, the end of BSS space can be found via:

Code: Select all

#asm
   EXTERN __BSS_END_tail
   ld  hl,__BSS_END_tail
#endasm
Or from C something like this should work:

Code: Select all

extern void *_BSS_END_tail;
#define BASS_END &_BSS_END_tail
The stack is impossible to tell - each CP/M machine will have a slightly different TPA and the stack usage of your program is unknown so your guess using the value of sp is as good as any.

The usage of sbrk makes more sense on a machine with a fragmented memory map - eg on the Spectrum the default is to load programs to 32768. The main heap will go after it, but there's unused memory below 32768 which could be added into the heap using sbrk.
oPless
New member
Posts: 3
Joined: Fri Jul 12, 2019 11:45 pm

Post by oPless »

Thanks very much for all of your answers!

Now I have to fix my build environment as clion has managed to break the z88dk target that I had set up :lol:
Post Reply