| View previous topic :: View next topic |
| Author |
Message |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Tue Jan 24, 2006 1:47 am Post subject: Free memory available functions |
|
|
Hello, i have coded little functions to know all memory available and maximum lineare memory available :
Header :
| Code: |
#ifndef RAM_INCLUDED
#define RAM_INCLUDED
/* RAM simple check functions header */
// *** INCLUDES ***
#include <psptypes.h>
#include <malloc.h>
// *** DEFINES ***
#define RAM_BLOCK (1024 * 1024)
// *** FUNCTIONS DECLARATIONS ***
u32 ramAvailableLineareMax (void);
u32 ramAvailable (void);
#endif
|
Source :
| Code: |
/* RAM simple check functions source */
// *** INCLUDES ***
#include "ram.h"
// *** FUNCTIONS ***
u32 ramAavailableLineareMax (void)
{
u32 size, sizeblock;
u8 *ram;
// Init variables
size = 0;
sizeblock = RAM_BLOCK;
// Check loop
while (sizeblock)
{
// Increment size
size += sizeblock;
// Allocate ram
ram = malloc(size);
// Check allocate
if (!(ram))
{
// Restore old size
size -= sizeblock;
// Size block / 2
sizeblock >>= 1;
}
else
free(ram);
}
return size;
}
u32 ramAvailable (void)
{
u8 **ram, **temp;
u32 size, count, x;
// Init variables
ram = NULL;
size = 0;
count = 0;
// Check loop
for (;;)
{
// Check size entries
if (!(count % 10))
{
// Allocate more entries if needed
temp = realloc(ram,sizeof(u8 *) * (count + 10));
if (!(temp)) break;
// Update entries and size (size contains also size of entries)
ram = temp;
size += (sizeof(u8 *) * 10);
}
// Find max lineare size available
x = ramAvailableLineareMax();
if (!(x)) break;
// Allocate ram
ram[count] = malloc(x);
if (!(ram[count])) break;
// Update variables
size += x;
count++;
}
// Free ram
if (ram)
{
for (x=0;x<count;x++) free(ram[x]);
free(ram);
}
return size;
}
|
Last edited by johnmph on Tue Jan 24, 2006 2:59 am; edited 1 time in total |
|
| Back to top |
|
 |
AnonymousTipster
Joined: 01 Jul 2005 Posts: 197
|
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Tue Jan 24, 2006 3:16 am Post subject: |
|
|
Thanks, yes it's similary.
I have coded a little sample for test it :
| Code: |
int main (void)
{
int x;
u8 **ram;
pspDebugScreenInit();
pspDebugScreenClear();
SetupCallbacks();
printf("Memory available before : %d\n",ramAvailable());
ram = malloc(100 * sizeof(u8 *));
if (ram)
{
memset(ram,0,sizeof(u8 *) * 100);
for (x=0;x<100;x++) ram[x] = malloc(1000);
printf("Memory available after malloc : %d\n",ramAvailable());
for (x=0;x<100;x++) if (ram[x]) free(ram[x]);
free(ram);
}
printf("Memory available after free : %d\n",ramAvailable());
printf("HOME for quit\n");
for (;;) sceDisplayWaitVblankStart();
sceKernelExitGame();
return 0;
}
|
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 ?? |
|
| Back to top |
|
 |
TyRaNiD
Joined: 18 Jan 2004 Posts: 918
|
Posted: Tue Jan 24, 2006 4:28 am Post subject: |
|
|
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: |
#include <malloc.h>
PSP_HEAP_SIZE_KB(20*1024);
...
struct mallinfo mi;
mi = mallinfo();
printf("freememory %dbytes\n", ((20*1024*1024) - mi.arena + mi.fordblks);
|
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. |
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Tue Jan 24, 2006 6:14 am Post subject: |
|
|
| 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: |
#include <malloc.h>
PSP_HEAP_SIZE_KB(20*1024);
...
struct mallinfo mi;
mi = mallinfo();
printf("freememory %dbytes\n", ((20*1024*1024) - mi.arena + mi.fordblks);
|
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: |
// Open file
fd = fopen(filename,"wb");
if (!(fd)) return 2;
// Create PNG write structure
pngWrite = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if (!(pngWrite))
{
fclose(fd);
return 3;
}
// Create PNG info structure
pngInfo = png_create_info_struct(pngWrite);
if (!(pngInfo))
{
png_destroy_write_struct(&pngWrite,png_infopp_NULL);
fclose(fd);
return 4;
}
// Write file
png_init_io(pngWrite,fd);
png_set_IHDR(pngWrite,pngInfo,image->width,image->height,8,PNG_COLOR_TYPE_RGB,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
png_write_info(pngWrite,pngInfo);
// Allocate one line
line = (u8 *) malloc(image->width * 3);
if (!(line))
{
png_destroy_write_struct(&pngWrite,&pngInfo);
fclose(fd);
return 5;
}
// Initialize bmp pointer
bmp = image->bmp;
// Height loop
for (y=0;y<image->height;y++)
{
// Width loop
for (x=0,x2=0;x<image->width;x++)
{
// Write pixel in line
line[x2++] = GRAPHIC_GET_COLOR_R(bmp[x]);
line[x2++] = GRAPHIC_GET_COLOR_G(bmp[x]);
line[x2++] = GRAPHIC_GET_COLOR_B(bmp[x]);
}
// Write line
png_write_row(pngWrite,line);
// Go to the next line
bmp += image->widthA;
}
// Free memory
free(line);
png_write_end(pngWrite,pngInfo);
png_destroy_write_struct(&pngWrite,&pngInfo);
fclose(fd);
return 0;
|
It's possible that png functions doesn't free correctly memory ??? |
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Thu Jan 26, 2006 3:56 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Thu Jan 26, 2006 4:52 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
Posted: Thu Jan 26, 2006 6:03 am Post subject: |
|
|
| 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. |
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Fri Jan 27, 2006 1:49 am Post subject: |
|
|
| 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: |
FILE *f;
printf("ram available before : %d\n",ramAvailable());
f=fopen("ms0:/test.bin","rb");
if (f) fclose(f);
printf("ram available after : %d\n",ramAvailable());
|
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). |
|
| Back to top |
|
 |
dot_blank

Joined: 28 Sep 2005 Posts: 498 Location: Brasil
|
Posted: Thu Apr 13, 2006 4:34 pm Post subject: |
|
|
has this been remedied yet _________________ 10011011 00101010 11010111 10001001 10111010 |
|
| Back to top |
|
 |
PeterM
Joined: 31 Dec 2005 Posts: 125 Location: Edinburgh, UK
|
Posted: Thu Apr 13, 2006 6:32 pm Post subject: |
|
|
| 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. |
|
| Back to top |
|
 |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Sat Aug 05, 2006 1:48 am Post subject: |
|
|
| Code: | | printf("ESTIMATED FREE RAM: %d BYTES", ((20*1024*1024) - mi.arena + mi.fordblks); |
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>
? |
|
| Back to top |
|
 |
Raphael

Joined: 17 Jan 2006 Posts: 646 Location: Germany
|
Posted: Sat Aug 05, 2006 1:56 am Post subject: |
|
|
You sure you also did include these lines:
| Quote: | 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 |
|
| Back to top |
|
 |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Sat Aug 05, 2006 2:22 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Sat Aug 05, 2006 4:13 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
AnonymousTipster
Joined: 01 Jul 2005 Posts: 197
|
Posted: Sat Aug 05, 2006 4:22 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Sat Aug 05, 2006 7:02 am Post subject: |
|
|
| 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! |
|
| Back to top |
|
 |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Sat Aug 05, 2006 7:48 am Post subject: |
|
|
It even reports the same amount of memory,
if I start it from IRshell with an mp3 playing! |
|
| Back to top |
|
 |
siberianstar
Joined: 22 Jun 2006 Posts: 70
|
Posted: Wed Aug 09, 2006 10:44 pm Post subject: |
|
|
i wrote this in 2 seconds
| Code: | #include <malloc.h>
int __freemem()
{
void *ptrs[480];
int mem, x, i;
for (x = 0; x < 480; x++)
{
void *ptr = malloc(51200);
if (!ptr) break;
ptrs[x] = ptr;
}
mem = x * 51200;
for (i = 0; i < x; i++)
free(ptrs[i]);
return mem;
} |
simple and fast |
|
| Back to top |
|
 |
flatmush
Joined: 07 Aug 2007 Posts: 28 Location: Here
|
Posted: Sun Aug 26, 2007 6:20 am Post subject: |
|
|
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/index.php?topic=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: |
#define MEMORY_USER_SIZE 0x01800000
u32 memFreeSpace(u32 inAccuracy) {
if(!inAccuracy)
inAccuracy = 1;
u32 tempBlockSize = (MEMORY_USER_SIZE >> 1);
u32 tempTests;
for(tempTests = 0; tempBlockSize > inAccuracy; tempTests++)
tempBlockSize >>= 1;
tempBlockSize = (MEMORY_USER_SIZE >> 1);
void* tempPointers[tempTests];
u32 i;
u32 tempSpace = 0;
for(i = 0; i < tempTests; i++) {
tempPointers[i] = malloc(tempBlockSize);
tempSpace += (tempPointers[i] ? tempBlockSize : 0);
tempBlockSize >>= 1;
}
for(i = 0; i < tempTests; i++) {
if(tempPointers[i])
free(tempPointers[i]);
}
return tempSpace;
}
|
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). |
|
|
| Back to top |
|
 |
|