ngspice/src/frontend/com_sysinfo.c

480 lines
13 KiB
C
Raw Normal View History

2009-10-01 00:22:36 +02:00
/* Provide system information
2009-10-01 00:22:36 +02:00
LINUX: /proc file system
Windows: GlobalMemoryStatusEx, GetSystemInfo, GetVersionExA, RegQueryValueExA
Authors: Holger Vogt, Hendrik Vogt
2009-10-01 00:22:36 +02:00
*/
#include "ngspice/ngspice.h"
#include "ngspice/cpdefs.h"
#include "ngspice/fteext.h"
2010-10-16 19:09:46 +02:00
#include "com_commands.h"
2009-10-01 00:22:36 +02:00
/* We might compile for Windows, but only as a console application (e.g. tcl) */
#if defined(HAS_WINGUI) || defined(__MINGW32__) || defined(_MSC_VER)
2009-10-01 00:22:36 +02:00
#define HAVE_WIN32
#endif
#ifdef HAVE_WIN32
#define WIN32_LEAN_AND_MEAN
2009-10-01 00:22:36 +02:00
#ifdef __MINGW32__ /* access to GlobalMemoryStatusEx in winbase.h:1558 */
#define WINVER 0x0500
#endif
#undef BOOLEAN
#include "windows.h"
#if defined(__MINGW32__) || (_MSC_VER > 1200) /* Exclude VC++ 6.0 from using the psapi */
#include <psapi.h>
#endif
#endif
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define tInt int
#define TesError int
#define TES_FAIL 1
#define TES_SUCCESS 0
2009-10-01 00:52:52 +02:00
#define TES_INVALID_PARAMS 1
2009-10-01 00:22:36 +02:00
/* system info */
typedef struct TSI {
char *cpuModelName;
unsigned numPhysicalProcessors;
unsigned numLogicalProcessors;
char *osName;
2009-10-01 00:22:36 +02:00
} TesSystemInfo;
/* memory info */
struct sys_memory {
unsigned long long size_m; /* Total memory size */
unsigned long long free_m; /* Free memory */
unsigned long long swap_t; /* Swap total */
unsigned long long swap_f; /* Swap free */
2009-10-01 00:22:36 +02:00
};
static struct sys_memory mem_t_act;
2009-10-01 00:22:36 +02:00
TesError tesCreateSystemInfo(TesSystemInfo *info);
static int get_sysmem(struct sys_memory *memall);
2009-10-01 00:22:36 +02:00
2009-10-01 00:22:36 +02:00
/* Print to stream the given memory size in a human friendly format */
static void
fprintmem(FILE *stream, unsigned long long memory)
{
2011-08-06 09:53:48 +02:00
if (memory > 1048576)
fprintf(stream, "%8.6f MB", (double)memory /1048576.);
2011-08-06 09:53:48 +02:00
else if (memory > 1024)
fprintf(stream, "%5.3f kB", (double)memory / 1024.);
2009-10-01 00:22:36 +02:00
else
fprintf(stream, "%u bytes", (unsigned)memory);
2009-10-01 00:22:36 +02:00
}
static void
tesFreeSystemInfo(TesSystemInfo *info)
{
if (info != NULL) {
free(info->cpuModelName);
free(info->osName);
}
2009-10-01 00:22:36 +02:00
}
2009-10-01 00:22:36 +02:00
/* print system info */
void
com_sysinfo(wordlist *wl)
2009-10-01 00:22:36 +02:00
{
int errorcode;
TesSystemInfo *info;
NG_IGNORE(wl);
info = TMALLOC(TesSystemInfo, 1);
errorcode = tesCreateSystemInfo(info);
if (errorcode) {
fprintf(cp_err, "No system info available! \n");
} else {
fprintf(cp_out, "\nOS: %s\n", info->osName);
fprintf(cp_out, "CPU: %s\n", info->cpuModelName);
if (info->numPhysicalProcessors > 0)
fprintf(cp_out, "Physical processors: %u, ", info->numPhysicalProcessors);
fprintf(cp_out, "Logical processors: %u\n",
info->numLogicalProcessors);
}
#if defined(HAVE_WIN32) || defined(HAVE__PROC_MEMINFO)
get_sysmem(&mem_t_act);
/* get_sysmem returns bytes */
fprintf(cp_out, "Total DRAM available = ");
fprintmem(cp_out, mem_t_act.size_m);
fprintf(cp_out, ".\n");
fprintf(cp_out, "DRAM currently available = ");
fprintmem(cp_out, mem_t_act.free_m);
fprintf(cp_out, ".\n\n");
2009-10-01 00:22:36 +02:00
#endif
tesFreeSystemInfo(info);
tfree(info);
2009-10-01 00:22:36 +02:00
}
#ifdef HAVE__PROC_MEMINFO
2009-10-01 00:22:36 +02:00
/* Get memory information */
static int
get_sysmem(struct sys_memory *memall)
{
FILE *fp;
char buffer[2048];
size_t bytes_read;
char *match;
unsigned long mem_got;
if ((fp = fopen("/proc/meminfo", "r")) == NULL) {
perror("fopen(\"/proc/meminfo\")");
return 0;
}
2009-10-01 00:22:36 +02:00
bytes_read = fread(buffer, 1, sizeof(buffer), fp);
fclose(fp);
if (bytes_read == 0 || bytes_read == sizeof(buffer))
return 0;
buffer[bytes_read] = '\0';
/* Search for string "MemTotal" */
match = strstr(buffer, "MemTotal");
if (match == NULL) /* not found */
return 0;
sscanf(match, "MemTotal: %ld", &mem_got);
memall->size_m = mem_got*1024; /* 1MB = 1024KB */
/* Search for string "MemFree" */
match = strstr(buffer, "MemFree");
if (match == NULL) /* not found */
return 0;
sscanf(match, "MemFree: %ld", &mem_got);
memall->free_m = mem_got*1024; /* 1MB = 1024KB */
/* Search for string "SwapTotal" */
match = strstr(buffer, "SwapTotal");
if (match == NULL) /* not found */
return 0;
sscanf(match, "SwapTotal: %ld", &mem_got);
memall->swap_t = mem_got*1024; /* 1MB = 1024KB */
/* Search for string "SwapFree" */
match = strstr(buffer, "SwapFree");
if (match == NULL) /* not found */
return 0;
sscanf(match, "SwapFree: %ld", &mem_got);
memall->swap_f = mem_got*1024; /* 1MB = 1024KB */
return 1;
}
2009-10-01 00:22:36 +02:00
/* Return length of first line in a string */
static size_t
getLineLength(const char *str)
{
const char *p = str;
while (*p && (*p != '\n'))
p++;
return (size_t) (p - str);
2009-10-01 00:22:36 +02:00
}
2009-10-01 00:22:36 +02:00
/* Checks if number 'match' is found in a vector 'set' of size 'size'
Returns 1 if yes, otherwise, 0 */
static tInt
searchInSet(const tInt *set, unsigned size, tInt match)
{
unsigned index;
for (index = 0; index < size; index++)
if (match == set[index])
return 1;
return 0;
2009-10-01 00:22:36 +02:00
}
2009-10-01 00:22:36 +02:00
/* Get system information */
TesError
tesCreateSystemInfo(TesSystemInfo *info)
{
FILE *file;
TesError error = TES_SUCCESS;
if (info == NULL)
return TES_INVALID_PARAMS;
info->cpuModelName = NULL;
info->osName = NULL;
info->numLogicalProcessors = info->numPhysicalProcessors = 0;
/* get kernel version string */
file = fopen("/proc/version", "rb");
if (file != NULL) {
size_t size;
/* read bytes and find end of file */
for (size = 0; ; size++)
if (EOF == fgetc(file))
break;
info->osName = TMALLOC(char, size);
rewind(file);
fread(info->osName, sizeof(char), size, file);
fclose(file);
info->osName[size-1] = '\0';
} else {
error = TES_FAIL;
}
/* get cpu information */
file = fopen("/proc/cpuinfo", "rb");
if (file != NULL) {
size_t size;
char *inStr;
/* read bytes and find end of file */
for (size = 0; ; size++)
if (EOF == fgetc(file))
break;
/* get complete string */
inStr = TMALLOC(char, size+1);
rewind(file);
fread(inStr, sizeof(char), size, file);
inStr[size] = '\0';
{
const char *matchStr = "model name";
/* pointer to first occurrence of model name*/
const char *modelStr = strstr(inStr, matchStr);
if (modelStr != NULL) {
/* search for ':' */
const char *modelPtr = strchr(modelStr, ':');
if (modelPtr != NULL) {
/*length of string from ':' till end of line */
size_t numToEOL = getLineLength(modelPtr);
if (numToEOL > 2) {
/* skip ": "*/
numToEOL -= 2;
info->cpuModelName = TMALLOC(char, numToEOL+1);
memcpy(info->cpuModelName, modelPtr+2, numToEOL);
info->cpuModelName[numToEOL] = '\0';
}
} else {
error = TES_FAIL;
}
} else {
error = TES_FAIL;
2009-10-01 00:22:36 +02:00
}
}
{
const char *matchStrProc = "processor";
const char *matchStrPhys = "physical id";
char *strPtr = inStr;
unsigned numProcs = 0;
tInt *physIDs;
/* get number of logical processors */
while ((strPtr = strstr(strPtr, matchStrProc)) != NULL) {
// numProcs++;
strPtr += strlen(matchStrProc);
if (isblank(*strPtr)) numProcs++;
}
info->numLogicalProcessors = numProcs;
physIDs = TMALLOC(tInt, numProcs);
/* get number of physical CPUs */
numProcs = 0;
strPtr = inStr;
while ((strPtr = strstr(strPtr, matchStrProc)) != NULL) {
/* search for first occurrence of physical id */
strPtr = strstr(strPtr, matchStrPhys);
if (strPtr != NULL) {
/* go to ';' */
strPtr = strchr(strPtr, ':');
if (strPtr != NULL) {
tInt buffer = 0;
/* skip ": " */
strPtr += 2;
/* get number */
sscanf(strPtr, "%d", &buffer);
/* If this physical id is unique,
we have another physically available CPU */
if (searchInSet(physIDs, numProcs, buffer) == 0) {
physIDs[numProcs] = buffer;
numProcs++;
}
} else {
// error = TES_FAIL;
break;
}
} else {
// error = TES_FAIL;
break;
}
}
info->numPhysicalProcessors = numProcs;
free(physIDs);
}
/* another test to get number of logical processors
* if (info->numLogicalProcessors == 0) {
* char *token;
* char *cpustr = copy(inStr);
2013-07-24 20:58:34 +02:00
* while (cpustr && !*cpustr)
* if (cieq(gettok(&cpustr), "processor")) {
* gettok(&cpustr);
* token = gettok(&cpustr);
* }
*
* info->numLogicalProcessors = atoi(token) + 1;
* tfree(cpustr);
* }
*/
free(inStr);
fclose(file);
} else {
error = TES_FAIL;
}
return error;
2009-10-01 00:22:36 +02:00
}
#elif defined(HAVE_WIN32)
2009-10-01 00:22:36 +02:00
/* get memory information */
static int
get_sysmem(struct sys_memory *memall)
{
#if (_WIN32_WINNT >= 0x0500)
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&ms);
memall->size_m = ms.ullTotalPhys;
memall->free_m = ms.ullAvailPhys;
memall->swap_t = ms.ullTotalPageFile;
memall->swap_f = ms.ullAvailPageFile;
2009-10-01 00:22:36 +02:00
#else
MEMORYSTATUS ms;
ms.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&ms);
memall->size_m = ms.dwTotalPhys;
memall->free_m = ms.dwAvailPhys;
memall->swap_t = ms.dwTotalPageFile;
memall->swap_f = ms.dwAvailPageFile;
#endif
return 1;
2009-10-01 00:22:36 +02:00
}
2009-10-01 00:22:36 +02:00
/* get system information */
TesError
tesCreateSystemInfo(TesSystemInfo *info)
{
OSVERSIONINFOA version;
char *versionStr = NULL, *procStr, *freeStr;
DWORD major, minor;
DWORD dwLen;
HKEY hkBaseCPU;
LONG lResult;
2009-10-01 00:22:36 +02:00
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
info->numPhysicalProcessors = 0;
info->numLogicalProcessors = sysinfo.dwNumberOfProcessors; //atoi(getenv("NUMBER_OF_PROCESSORS"));
info->osName = NULL;
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if (GetVersionExA(&version) == 0)
return TES_FAIL;
major = version.dwMajorVersion;
minor = version.dwMinorVersion;
switch (major) {
case 4:
if (minor == 0)
versionStr = "Windows 95/NT4.0";
else if (minor == 10)
versionStr = "Windows 98";
else if (minor == 90)
versionStr = "Windows ME";
break;
case 5:
if (minor == 0)
versionStr = "Windows 2000";
else if (minor == 1)
versionStr = "Windows XP";
else if (minor == 2)
versionStr = "Windows Server 2003";
break;
case 6:
if (minor == 0)
versionStr = "Windows Vista";
else if (minor == 1)
versionStr = "Windows 7";
break;
default:
break;
}
2009-10-01 00:22:36 +02:00
if (versionStr != NULL) {
size_t lengthCSD = strlen(version.szCSDVersion);
size_t lengthVer = strlen(versionStr);
info->osName = TMALLOC(char, lengthVer + lengthCSD + 2);
memcpy(info->osName, versionStr, lengthVer);
memcpy(info->osName + lengthVer + 1, version.szCSDVersion, lengthCSD);
info->osName[lengthVer] = ' ';
info->osName[lengthVer + lengthCSD + 1] = '\0';
}
2009-10-01 00:22:36 +02:00
lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
0, KEY_READ, &hkBaseCPU);
if (lResult != ERROR_SUCCESS) {
info->cpuModelName = NULL;
return TES_FAIL;
2009-10-01 00:22:36 +02:00
}
RegQueryValueExA(hkBaseCPU, "ProcessorNameString", 0, 0, NULL, &dwLen);
freeStr = procStr = TMALLOC(char, dwLen + 1);
RegQueryValueExA(hkBaseCPU, "ProcessorNameString", 0, 0, (LPBYTE)procStr, &dwLen);
2009-10-01 00:22:36 +02:00
procStr[dwLen] = '\0';
while (*procStr == ' ')
procStr++;
2009-10-01 00:22:36 +02:00
info->cpuModelName = copy(procStr);
tfree(freeStr);
RegCloseKey(hkBaseCPU);
2009-10-01 00:22:36 +02:00
return TES_SUCCESS;
2009-10-01 00:22:36 +02:00
}
#else
2009-10-01 00:22:36 +02:00
/* no Windows OS, no proc info file system */
TesError
tesCreateSystemInfo(TesSystemInfo *info)
{
return 1;
2009-10-01 00:22:36 +02:00
}
#endif