Free memory available functions

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
johnmph
Posts: 119
Joined: Sat Jul 23, 2005 11:48 pm

Free memory available functions

Post by johnmph »

Hello, i have coded little functions to know all memory available and maximum lineare memory available :

Header :

Code: Select all


#ifndef RAM_INCLUDED
#define RAM_INCLUDED

/* RAM simple check functions header */


// *** INCLUDES ***

#include <psptypes.h>
#include <malloc.h>


// *** DEFINES ***

#define RAM_BLOCK		&#40;1024 * 1024&#41;


// *** FUNCTIONS DECLARATIONS ***

u32 ramAvailableLineareMax &#40;void&#41;;
u32 ramAvailable &#40;void&#41;;

#endif

Source :

Code: Select all


/* RAM simple check functions source */


// *** INCLUDES ***

#include "ram.h"


// *** FUNCTIONS ***

u32 ramAavailableLineareMax &#40;void&#41;
&#123;
 u32 size, sizeblock;
 u8 *ram;


 // Init variables
 size = 0;
 sizeblock = RAM_BLOCK;

 // Check loop
 while &#40;sizeblock&#41;
 &#123;
  // Increment size
  size += sizeblock;

  // Allocate ram
  ram = malloc&#40;size&#41;;

  // Check allocate
  if &#40;!&#40;ram&#41;&#41;
  &#123;
   // Restore old size
   size -= sizeblock;

   // Size block / 2
   sizeblock >>= 1;
  &#125;
  else
   free&#40;ram&#41;;
 &#125;

 return size;
&#125;

u32 ramAvailable &#40;void&#41;
&#123;
 u8 **ram, **temp;
 u32 size, count, x;


 // Init variables
 ram = NULL;
 size = 0;
 count = 0;

 // Check loop
 for &#40;;;&#41;
 &#123;
  // Check size entries
  if &#40;!&#40;count % 10&#41;&#41;
  &#123;
   // Allocate more entries if needed
   temp = realloc&#40;ram,sizeof&#40;u8 *&#41; * &#40;count + 10&#41;&#41;;
   if &#40;!&#40;temp&#41;&#41; break;
  
   // Update entries and size &#40;size contains also size of entries&#41;
   ram = temp;
   size += &#40;sizeof&#40;u8 *&#41; * 10&#41;;
  &#125;

  // Find max lineare size available
  x = ramAvailableLineareMax&#40;&#41;;
  if &#40;!&#40;x&#41;&#41; break;

  // Allocate ram
  ram&#91;count&#93; = malloc&#40;x&#41;;
  if &#40;!&#40;ram&#91;count&#93;&#41;&#41; break;

  // Update variables
  size += x;
  count++;
 &#125;

 // Free ram
 if &#40;ram&#41;
 &#123;
  for &#40;x=0;x<count;x++&#41; free&#40;ram&#91;x&#93;&#41;;
  free&#40;ram&#41;;
 &#125;

 return size;
&#125;

Last edited by johnmph on Tue Jan 24, 2006 2:59 am, edited 1 time in total.
AnonymousTipster
Posts: 197
Joined: Fri Jul 01, 2005 2:50 am

Post by AnonymousTipster »

I also coded one a week or so ago:
http://forums.ps2dev.org/viewtopic.php? ... t=ram+free
Which calculates to 0.1MB each time. Yours is more elegant, though.
johnmph
Posts: 119
Joined: Sat Jul 23, 2005 11:48 pm

Post by johnmph »

AnonymousTipster wrote:I also coded one a week or so ago:
http://forums.ps2dev.org/viewtopic.php? ... t=ram+free
Which calculates to 0.1MB each time. Yours is more elegant, though.
Thanks, yes it's similary.

I have coded a little sample for test it :

Code: Select all


int main &#40;void&#41;
&#123;
 int x;
 u8 **ram;


 pspDebugScreenInit&#40;&#41;;
 pspDebugScreenClear&#40;&#41;;
 SetupCallbacks&#40;&#41;;


 printf&#40;"Memory available before &#58; %d\n",ramAvailable&#40;&#41;&#41;;

 ram = malloc&#40;100 * sizeof&#40;u8 *&#41;&#41;;

 if &#40;ram&#41;
 &#123;
  memset&#40;ram,0,sizeof&#40;u8 *&#41; * 100&#41;;

  for &#40;x=0;x<100;x++&#41; ram&#91;x&#93; = malloc&#40;1000&#41;;

  printf&#40;"Memory available after malloc &#58; %d\n",ramAvailable&#40;&#41;&#41;;

  for &#40;x=0;x<100;x++&#41; if &#40;ram&#91;x&#93;&#41; free&#40;ram&#91;x&#93;&#41;;

  free&#40;ram&#41;;
 &#125;

 printf&#40;"Memory available after free &#58; %d\n",ramAvailable&#40;&#41;&#41;;

 printf&#40;"HOME for quit\n"&#41;;
 for &#40;;;&#41; sceDisplayWaitVblankStart&#40;&#41;;

 sceKernelExitGame&#40;&#41;;

 return 0;
&#125;

The program allocates 100 blocks of 1000 bytes (100000 bytes) + array of pointers to these blocks (100 * sizeof(U8 *) -> 100 * 4 = 400) = 100400 bytes.


When the program begins, it shows the free memory available before it allocates block :

23551384 bytes

and after block allocation :

23450176 bytes

but 23551384 - 100400 = 23450984 bytes

23450984 - 23450176 = 808 bytes

What is these 808 bytes ?, malloc structure informations ?, alignement of memory ??
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Of course if you know your heap size (by using the PSP_HEAP_SIZE_KB macro) you can find the free space pretty easily.

Code: Select all

#include <malloc.h>

PSP_HEAP_SIZE_KB&#40;20*1024&#41;;

...

   struct mallinfo mi;

   mi = mallinfo&#40;&#41;;
   printf&#40;"freememory %dbytes\n", &#40;&#40;20*1024*1024&#41; - mi.arena + mi.fordblks&#41;;
Perhaps it would be a good idea to provide an accessor to get the ELF allocated heap size (which is as much memory as it can get) into newlib so you can do this sort of calculation trivially.

There does seem to be some wastage as you point out, probably for alignment and control structures I guess, not 100% sure without digging into the malloc routines ;) I also don't know how to easily determine the largest contiguous block available without doing something like you are doing.
johnmph
Posts: 119
Joined: Sat Jul 23, 2005 11:48 pm

Post by johnmph »

TyRaNiD wrote:Of course if you know your heap size (by using the PSP_HEAP_SIZE_KB macro) you can find the free space pretty easily.

Code: Select all

#include <malloc.h>

PSP_HEAP_SIZE_KB&#40;20*1024&#41;;

...

   struct mallinfo mi;

   mi = mallinfo&#40;&#41;;
   printf&#40;"freememory %dbytes\n", &#40;&#40;20*1024*1024&#41; - mi.arena + mi.fordblks&#41;;
Perhaps it would be a good idea to provide an accessor to get the ELF allocated heap size (which is as much memory as it can get) into newlib so you can do this sort of calculation trivially.

There does seem to be some wastage as you point out, probably for alignment and control structures I guess, not 100% sure without digging into the malloc routines ;) I also don't know how to easily determine the largest contiguous block available without doing something like you are doing.
Thanks for mallinfo tricks ;-).

In fact, i have coded these functions to know if in my code, i didn't forget to free all memory.

But when i use a simple png load or save function, not all the memory is free (+- 400 bytes lost).

This is the save function, i have checked it and i don't found any errors :

Code: Select all


 // Open file
 fd = fopen&#40;filename,"wb"&#41;;
 if &#40;!&#40;fd&#41;&#41; return 2;

 // Create PNG write structure
 pngWrite = png_create_write_struct&#40;PNG_LIBPNG_VER_STRING,NULL,NULL,NULL&#41;;
 if &#40;!&#40;pngWrite&#41;&#41;
 &#123;
  fclose&#40;fd&#41;;

  return 3;
 &#125;

 // Create PNG info structure
 pngInfo = png_create_info_struct&#40;pngWrite&#41;;
 if &#40;!&#40;pngInfo&#41;&#41;
 &#123;
  png_destroy_write_struct&#40;&pngWrite,png_infopp_NULL&#41;;
  fclose&#40;fd&#41;;

  return 4;
 &#125;

 // Write file
 png_init_io&#40;pngWrite,fd&#41;;
 png_set_IHDR&#40;pngWrite,pngInfo,image->width,image->height,8,PNG_COLOR_TYPE_RGB,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT&#41;;
 png_write_info&#40;pngWrite,pngInfo&#41;;

 // Allocate one line
 line = &#40;u8 *&#41; malloc&#40;image->width * 3&#41;;
 if &#40;!&#40;line&#41;&#41;
 &#123;
  png_destroy_write_struct&#40;&pngWrite,&pngInfo&#41;;
  fclose&#40;fd&#41;;

  return 5;
 &#125;

 // Initialize bmp pointer
 bmp = image->bmp;

 // Height loop
 for &#40;y=0;y<image->height;y++&#41; 
 &#123;
  // Width loop
  for &#40;x=0,x2=0;x<image->width;x++&#41;
  &#123;
   // Write pixel in line
   line&#91;x2++&#93; = GRAPHIC_GET_COLOR_R&#40;bmp&#91;x&#93;&#41;;
   line&#91;x2++&#93; = GRAPHIC_GET_COLOR_G&#40;bmp&#91;x&#93;&#41;;
   line&#91;x2++&#93; = GRAPHIC_GET_COLOR_B&#40;bmp&#91;x&#93;&#41;;
  &#125;

  // Write line
  png_write_row&#40;pngWrite,line&#41;;

  // Go to the next line
  bmp += image->widthA;
 &#125;

 // Free memory
 free&#40;line&#41;;
 png_write_end&#40;pngWrite,pngInfo&#41;;
 png_destroy_write_struct&#40;&pngWrite,&pngInfo&#41;;
 fclose&#40;fd&#41;;

 return 0;


It's possible that png functions doesn't free correctly memory ???
johnmph
Posts: 119
Joined: Sat Jul 23, 2005 11:48 pm

Post by johnmph »

With these functions, i have found some errors (forget to free memory) in my code, now the code is clean ;-) WITHOUT png functions.

I have coded a little bmp load function to test it and the program works and all memory is free but if i use png functions instead my bmp functions, there is always these bytes lost (+- 400).

I think seriously that png functions doesn't free all memory.
johnmph
Posts: 119
Joined: Sat Jul 23, 2005 11:48 pm

Post by johnmph »

I have found the function that cause the bytes lost, it's fopen.

When i use fopen and fclose, 384 bytes are lost, maybe it's normal, i don't know.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

How about just open() and close()? We allocate some mem in open() but it should get freed in close(). If the problem is just fopen/fclose, it's probably the internal buffering that newlib does; we didn't touch that code but it might be buggy.
johnmph
Posts: 119
Joined: Sat Jul 23, 2005 11:48 pm

Post by johnmph »

jimparis wrote:How about just open() and close()? We allocate some mem in open() but it should get freed in close(). If the problem is just fopen/fclose, it's probably the internal buffering that newlib does; we didn't touch that code but it might be buggy.
The problem is just fopen/fclose, if you write a little program like :

Code: Select all


FILE *f;

printf&#40;"ram available before &#58; %d\n",ramAvailable&#40;&#41;&#41;;

f=fopen&#40;"ms0&#58;/test.bin","rb"&#41;;
if &#40;f&#41; fclose&#40;f&#41;;

printf&#40;"ram available after &#58; %d\n",ramAvailable&#40;&#41;&#41;;

The ram available after has 384 bytes less than before the fopen/fclose call even if the file is not opened (if the file doesn't exist).
User avatar
dot_blank
Posts: 498
Joined: Wed Sep 28, 2005 8:47 am
Location: Brasil

Post by dot_blank »

has this been remedied yet
10011011 00101010 11010111 10001001 10111010
PeterM
Posts: 125
Joined: Sat Dec 31, 2005 7:25 pm
Location: Edinburgh, UK
Contact:

Post by PeterM »

Is it something that needs fixed? I'm quite happy for functions to maintain an internal buffer, as long as they don't leak each time they're called.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Code: Select all

	printf&#40;"ESTIMATED FREE RAM&#58; %d BYTES", &#40;&#40;20*1024*1024&#41; - mi.arena + mi.fordblks&#41;; 
I'm not having the best time with it...
any idea why I get a syntax error in this line when I have included
include <malloc.h>
?
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

You sure you also did include these lines:
PSP_HEAP_SIZE_KB(20*1024);

...

struct mallinfo mi;

mi = mallinfo();
They are crucial for this method to work.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Doh, I think I put the bottom two lines inside the function.. which is probably wrong.

I *think* I have johnMPH's code working now... just got to use more
or less RAM to check it.
Cheers, Art.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Although the function appears to work,
My program reports the same amount of available memory right down
to the exact byte whether it was started from IRshell or not.

IRshell must use some memory.. it hangs around because you can use
the note button to take a screenshot when your app is running.. so it must
be running somethng that uses RAM.
AnonymousTipster
Posts: 197
Joined: Fri Jul 01, 2005 2:50 am

Post by AnonymousTipster »

Actually, iRShell resides almost entirely in kernel memory space and only breaks into user space with wifi and image viewing functions.
I think a better way to detect if running from a shell is to look at the psplink source to find what modules are running, and see if there are any more than usual.
You might want to ask Tyranid about this though, as the number may fluctuate, and I think it may also require a kernel mode application to work.
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

AnonymousTipster wrote:Actually, iRShell resides almost entirely in kernel memory space and only breaks into user space with wifi and image viewing functions.
I think a better way to detect if running from a shell is to look at the psplink source to find what modules are running, and see if there are any more than usual.
You might want to ask Tyranid about this though, as the number may fluctuate, and I think it may also require a kernel mode application to work.
You should be able to get sufficient info from the user-mode module info functions for these purposes, kernel isn't necessary.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

It even reports the same amount of memory,
if I start it from IRshell with an mp3 playing!
siberianstar
Posts: 70
Joined: Thu Jun 22, 2006 9:24 pm

Post by siberianstar »

i wrote this in 2 seconds

Code: Select all

#include <malloc.h>
int __freemem&#40;&#41;
&#123;
 void *ptrs&#91;480&#93;;
 int mem, x, i;
 for &#40;x = 0; x < 480; x++&#41;
 &#123;
    void *ptr = malloc&#40;51200&#41;;
    if &#40;!ptr&#41; break;
 
    ptrs&#91;x&#93; = ptr;
 &#125;
 mem = x * 51200;
 for &#40;i = 0; i < x; i++&#41;
  free&#40;ptrs&#91;i&#93;&#41;;

 return mem;
&#125;
simple and fast
flatmush
Posts: 28
Joined: Tue Aug 07, 2007 9:15 am
Location: Here
Contact:

Post by flatmush »

Well I made quite a large post on psp-programming that is quite relevant to this topic, I hate to link to another forum but there seems little point in replicating the post here as it's quite large.
You will find a better free space function and lots of other memory related info here: http://www.psp-programming.com/forums/i ... pic=2731.0
Old Post wrote:Hate to bring up an old topic, but as it's a recurring question and this is the main thread for the answers to this question, I thought I'd post my algorithm.

This should be faster and more accurate than most the previous methods (except TyRaNiDs).

Code: Select all

#define MEMORY_USER_SIZE 0x01800000

u32 memFreeSpace&#40;u32 inAccuracy&#41; &#123;
    if&#40;!inAccuracy&#41;
         inAccuracy = 1;

    u32 tempBlockSize = &#40;MEMORY_USER_SIZE >> 1&#41;;
    u32 tempTests;
    
    for&#40;tempTests = 0; tempBlockSize > inAccuracy; tempTests++&#41;
         tempBlockSize >>= 1;
    tempBlockSize = &#40;MEMORY_USER_SIZE >> 1&#41;;

    void* tempPointers&#91;tempTests&#93;;
    
    u32 i; 
    u32 tempSpace = 0;
    for&#40;i = 0; i < tempTests; i++&#41; &#123;
         tempPointers&#91;i&#93; = malloc&#40;tempBlockSize&#41;;
         tempSpace += &#40;tempPointers&#91;i&#93; ? tempBlockSize &#58; 0&#41;;
         tempBlockSize >>= 1;
    &#125;
    
    for&#40;i = 0; i < tempTests; i++&#41; &#123;
         if&#40;tempPointers&#91;i&#93;&#41;
              free&#40;tempPointers&#91;i&#93;&#41;;
    &#125;
    
    return tempSpace;
&#125;
The inAccuracy parameter is how accurate you want the results to be, so 1 would give you the number of bytes, and 1024 would give the whole number of kilobytes etc.

EDIT: oops I feel stupid now, this will only work if your memory isn't fragmented at all, I'll have to think of a different approach (maybe recursive).
Post Reply