[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]

Re: [XaraXtreme-dev] [patch] Have implemented a Linux port of GetMemoryStatus ("Function to find available RAM")



Hello,

Alex Bligh wrote:
> Israel,
>
> Thanks for this. I will have a look in more detail in the morning but
> a couple of comments:
Sure, glad to be of help :)

> 1. (perhaps based on what Phil gave you) it seems to me that
>    we are doing #ifdef MSW, #elif #WXMAC, #else (assume Linux)
>    and then processing a /proc file. Well, that means FreeBSD
>    etc. will fail to compile because hey aren't Mac or MSW.
>    I think we should instead test for MSW (and use that if so),
>    then for Linux (explicitly) and use your code, then if that
>    fails, fail for Mac, FreeBSD etc. as well. That's better than
>    trying to open files that don't exist on FreeBSD. (I think
>    the /proc file is not going to exist on FreeBSD etc. - right
>    Vasil?)
I agree that an explicit test for Linux would be advantageous, since
this code is only really guaranteed to function (at runtime) on Linux
(BSD does not, to my knowledge, have a /proc/meminfo interface as Linux
does, although I believe it is possible to install some compatibility
packages to simulate some Linux features).

However, the code *will* definitely compile and run on any
ANSI-compliant system; in particular, it will compile and run on a BSD
system, Mac, and so on. The code can still be used as-is without
breaking anything, until a specific Linux check is added (and different
implementations are made for the non-Linux platforms).

Naturally, for non-Linux platforms, if the /proc/meminfo file does not
exist, the code will not be able to extract the relevant memory
information; however, it still falls back to a guess like the original
version did (please see below for more on that).

> 2. Minor nit: if the /proc file fails to open, it seems to me
>    that haveMemTotal and haveMemFree will be unitialized. They
>    should I think be initialized to zero, so if the open fails,
>    the appropriate default routines are called.
You are absolutely correct, it would make no sense otherwise. It was a
minor oversight on my part, I'm quite sure I had them initialized to 0
at some point but must have rewritten that line and forgot to put the
initializations back in. Clearly they need to be set to 0 upon
declaration, so that the verification below works and is able to fall
back to a 512MB 50% free guess (I took those values from the original code).

I am sending the revised patch, with the variables initialized this time
(that's the only difference).

Regards,
Israel

Index: memory.cpp
===================================================================
--- memory.cpp	(revision 1199)
+++ memory.cpp	(working copy)
@@ -118,6 +118,10 @@
 #include "ralphcri.h"
 #endif
 
+#if !defined(__WXMSW__) && !defined(__WXMAC__)
+#  include <stdio.h>
+#endif
+
 DECLARE_SOURCE("$Revision$");
 
 
@@ -1023,10 +1027,43 @@
 		if (pLoadPercent) *pLoadPercent = memStatus.dwMemoryLoad;
 		if (pPhysRam) *pPhysRam = memStatus.dwTotalPhys;
 	}
-#else
-	PORTNOTETRACE("other", "GetMemoryStatus is not implemented on this architecture");
+#elif defined(__WXMAC__)
+	PORTNOTETRACE("other", "GetMemoryStatus is not implemented for WXMAC");
 	if (pPhysRam) *pPhysRam = 512L * 1024 * 1024;	// Guess 512M
 	if (pLoadPercent) *pLoadPercent = 50;			// Guess 50% free
+#else
+	/* Linux: read memory information from the kernel's /proc/meminfo interface */
+	FILE *fp;
+	unsigned long memTotalKb, memFreeKb;
+	int haveMemTotal = 0, haveMemFree = 0;
+	char lineBuf[256];
+
+	fp = fopen("/proc/meminfo", "r");
+
+	if (fp != NULL)
+	{
+		while (!haveMemTotal || !haveMemFree)
+		{
+			if (fgets(lineBuf, 256, fp) == NULL)
+				break;
+
+			if (sscanf(lineBuf, "MemTotal: %lu", &memTotalKb) == 1)
+				haveMemTotal = 1;
+			if (sscanf(lineBuf, "MemFree: %lu", &memFreeKb) == 1)
+				haveMemFree = 1;
+		}
+		fclose(fp);
+	}
+
+	if (!haveMemTotal)
+		memTotalKb = 512UL * 1024;	/* guess 512MB */
+	if (!haveMemFree)
+		memFreeKb = memTotalKb / 2;	/* guess 50% free */
+
+	if (pPhysRam != NULL)
+		*pPhysRam = (UINT64)memTotalKb * 1024;
+	if (pLoadPercent != NULL)
+		*pLoadPercent = (UINT32)(100UL - ((memFreeKb * 100UL) / memTotalKb));
 #endif
 }