Understanding Dynamic Memory Allocation (malloc)

General Programming help in C, C++ or ASM, Compiling / Debugging, and R3000A Central Processing Unit (CPU) information
Post Reply
jman
Rookie Programmer
Rookie Programmer
Posts: 110
Joined: August 13th, 2013, 7:58 am

Understanding Dynamic Memory Allocation (malloc)

Post by jman » November 25th, 2013, 9:19 am

Hello,

I have a couple of questions concerning the functions for dynamic memory allocation.

1) Before using malloc3()/free3() it is necessary to execute InitHeap3(): if I understand correctly this should be invoked just once in the whole application lifecycle to clear the whole available heap, correct? What is the exact purpose of this function? What does it mean initializing the heap?

2) How do I calculate the available heap? According to this schema and from source sample found around, the formula is:

Code: Select all

typedef unsigned long u32;
unsigned long _ramsize = 0x00200000; // 2MB
unsigned long _stacksize = 0x00008000; // 32K
#define STACK 	(0x80000000 + _ramsize - _stacksize)

u32 heap_base[4];
InitHeap3((u32*)heap_base, STACK-(u32)heap_base);
I don't have clear heap_base. In the libref it is defined as the "pointer to heap start address" but I don't understand how those 4 bytes are used in the InitHeap3() function.

Thanks for any clarification.

User avatar
t0rxe
C Programming Expert
C Programming Expert
Posts: 140
Joined: December 19th, 2012, 8:08 pm
IRC: t0rxe
Motto: /\OX[]
PlayStation Model: SCPH-5502
Location: Australia

Re: Understanding Dynamic Memory Allocation (malloc)

Post by t0rxe » November 25th, 2013, 5:05 pm

Yes, you must initialise the heap. It only needs to be initialised once.

The code below will allocate 1MB of RAM as heap.
The heap is a set chunk of the remaining RAM that can only be used for malloc functions.
Any other RAM left can be used for other things if you wish, but it is wise to try and get as much of the RAM as you can into the heap, while leaving enough stack space for your game/program.

You should remember that the heap works its way down, starting from the stack:

Code: Select all

printf("\nReserving 1024KB (1,048,576 Bytes) RAM... ");
InitHeap3((void*)0x800F8000, 0x00100000);
printf("Success");
You can see this code is set to start from a 16KB stack (0x800F8000). If this is too small, you must recalculate and adjust it as needed.

The RAM and Stack are set using (though the RAM definition is only usually needed if you are working with the DTL-H2x00 development boards as they allow up to 8MB of RAM) :

Code: Select all

unsigned long __ramsize =   0x00200000; // 2 Megabytes of RAM
unsigned long __stacksize = 0x00004000; // 16 Kilobytes of Stack
Make sure you are also using MMGMNEW.OBJ during the compilation or else you will receive errors and may be using the old malloc libs.

And yes, here is my PSX RAM layout drawing: viewtopic.php?f=47&t=463
"Nostalgia isn't a big enough word to describe the PlayStation from my eyes"

jman
Rookie Programmer
Rookie Programmer
Posts: 110
Joined: August 13th, 2013, 7:58 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by jman » November 26th, 2013, 8:00 am

t0rxe wrote:Yes, you must initialise the heap. It only needs to be initialised once.
Why initialize the heap? In Linux you can initialize a malloc()'ed chunk of memory, but nothing is needed before AFAIK.
t0rxe wrote: Make sure you are also using MMGMNEW.OBJ during the compilation or else you will receive errors and may be using the old malloc libs.
Interesting, I didn't know that.
In case another googler passing by here, that OBJ file is located in the PsyQ devkit:

Code: Select all

C:\psyq>find . -iname MMGMNEW.OBJ
.\beta\mmgm\OBJ\MMGMNEW.OBJ
Thank you very much!

Tommy
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: April 19th, 2014, 8:16 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by Tommy » April 19th, 2014, 9:42 am

jman wrote: Why initialize the heap? In Linux you can initialize a malloc()'ed chunk of memory, but nothing is needed before AFAIK.
Any heap needs to be initialised before use — it's a data structure much like any other. The BIOS initialised the heap then, due to a buggy implementation, corrupts it before your code gets to run. So you have to reinitialise it to put it back into a valid state.

User avatar
nocash
PSX Aficionado
PSX Aficionado
Posts: 306
Joined: November 12th, 2012, 2:36 pm
Contact:

Re: Understanding Dynamic Memory Allocation (malloc)

Post by nocash » April 25th, 2014, 9:26 pm

Yeah, well, it tries to initialize the heap to EMPTY size, and does then corrupt that setting. But even without that bug you would need to initialize it yourself (assuming you want to the heap space to be bigger than 0 bytes).

Anyways, the reason why one must manually initialize the heap is that the PSX .EXE files don't contain info about how much memory is being used by the EXE file (except, of course, the filesize indicates how much code and initialized data is used, but doesn't give a hint on uninitialized data regions with hardcoded addresses, nor the amount of stack space that required for your program).
The BIOS simply cannot know much memory is used by the EXE and how much memory is available as heap.

jman
Rookie Programmer
Rookie Programmer
Posts: 110
Joined: August 13th, 2013, 7:58 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by jman » April 26th, 2014, 12:45 am

Thanks for the explainations :-)

Tommy
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: April 19th, 2014, 8:16 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by Tommy » April 26th, 2014, 6:01 am

nocash wrote:Yeah, well, it tries to initialize the heap to EMPTY size, and does then corrupt that setting. ...
If I dare head off at a tangent slightly, what you've done for documenting the PlayStation and in implementing your emulator/debugger is fantastic. I haven't found a single other emulator that bothers to do a proper hardware emulation and I couldn't be more impressed; I can understand why the high-level emulation stuff was justified a decade or more ago but I think you're taking the much more intelligent path now.

However... it leaves those of us that don't use Windows at a disadvantage. It looks like your app is a proper, native Win32 implementation, intended to fit properly with the OS that the vast majority of the world uses. So I suspect that portability wouldn't be easy and probably isn't a priority in any event? Is there any hope you'll be releasing your alternative BIOS and/or the logic related to detecting specific BIOS patches (if it's native rather than in-MIPS) for the benefit of lesser authors? Is there anything that might persuade you otherwise if not?

jman
Rookie Programmer
Rookie Programmer
Posts: 110
Joined: August 13th, 2013, 7:58 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by jman » May 4th, 2014, 7:48 am

I noticed another interesting thing: apparently GsIMAGE and GsSPRITE structs are already allocated when the application starts and they are *never* deallocated.
If I declare a global Gs* object and I print their address right at the beginning of the main() they are not null.

Should I be concerned and try to manually manage their lifecycle?

Tommy
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: April 19th, 2014, 8:16 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by Tommy » May 5th, 2014, 1:23 pm

jman wrote:I noticed another interesting thing: apparently GsIMAGE and GsSPRITE structs are already allocated when the application starts and they are *never* deallocated.
If I declare a global Gs* object and I print their address right at the beginning of the main() they are not null.

Should I be concerned and try to manually manage their lifecycle?
I may not be following what you're saying correctly but anything you declare as global, in any source file, will have the same lifetime as the application.

Sprite structs seem to be 36 bytes, image structs 28 bytes. So whether you should be concerned depends on how many of them you have multiplied by those sizes, I guess.

jman
Rookie Programmer
Rookie Programmer
Posts: 110
Joined: August 13th, 2013, 7:58 am

Re: Understanding Dynamic Memory Allocation (malloc)

Post by jman » May 6th, 2014, 6:40 am

@tommy, thanks for your reply, actually my quesiton was bad formed. What I meant is that if I declare a

Code: Select all

GsSPRITE spr
I have an object already usable while if I declare

Code: Select all

GsSPRITE *spr
I have a pointer that needs all the usual C treatment (malloc3(), free3(), ....).

At first this wasn't clear to me as I thought that GsXXX objects were structs pointers. They're not.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest