2000-04-27 22:03:57 +02:00
|
|
|
/**********
|
|
|
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
|
|
|
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
2005-05-21 14:24:09 +02:00
|
|
|
$Id$
|
2000-04-27 22:03:57 +02:00
|
|
|
**********/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Resource-related routines.
|
|
|
|
|
*/
|
|
|
|
|
|
2007-11-14 21:26:01 +01:00
|
|
|
#include "config.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
#include "ngspice.h"
|
|
|
|
|
#include "cpdefs.h"
|
|
|
|
|
#include "ftedefs.h"
|
|
|
|
|
|
2000-06-27 18:09:02 +02:00
|
|
|
#include "circuits.h"
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
#include "quote.h"
|
2000-06-27 18:09:02 +02:00
|
|
|
#include "resource.h"
|
|
|
|
|
#include "variable.h"
|
2005-09-08 11:44:32 +02:00
|
|
|
#include "cktdefs.h"
|
2007-11-14 21:26:01 +01:00
|
|
|
#include "src/misc/misc_time.h" /* timediff */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-06-30 16:38:21 +02:00
|
|
|
#ifdef XSPICE
|
|
|
|
|
/* gtri - add - 12/12/90 - wbk - include ipc stuff */
|
|
|
|
|
#include "ipctiein.h"
|
|
|
|
|
/* gtri - end - 12/12/90 */
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2002-01-03 23:44:21 +01:00
|
|
|
#ifdef HAVE__MEMAVL
|
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
2005-04-24 23:17:31 +02:00
|
|
|
/*
|
|
|
|
|
* The ngspice.h file included above defines BOOLEAN (via bool.h) and this
|
|
|
|
|
* clashes with the definition obtained from windows.h (via winnt.h).
|
|
|
|
|
* However, BOOLEAN is not used by this file so we can work round this problem
|
|
|
|
|
* by undefining BOOLEAN before including windows.h
|
|
|
|
|
* SJB - April 2005
|
|
|
|
|
*/
|
|
|
|
|
#undef BOOLEAN
|
2002-01-03 23:44:21 +01:00
|
|
|
#include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* static declarations */
|
|
|
|
|
static void printres(char *name);
|
2005-10-15 15:56:44 +02:00
|
|
|
static void fprintmem(FILE* stream, size_t memory);
|
2007-11-28 18:29:28 +01:00
|
|
|
#ifndef HAVE__MEMAVL
|
2000-04-27 22:03:57 +02:00
|
|
|
static RETSIGTYPE fault(void);
|
|
|
|
|
static void * baseaddr(void);
|
2007-11-28 18:29:28 +01:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2002-01-03 23:44:21 +01:00
|
|
|
#ifdef HAVE__MEMAVL
|
|
|
|
|
size_t mem_avail;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2002-01-03 23:44:21 +01:00
|
|
|
size_t _memavl(void)
|
|
|
|
|
{
|
2005-10-15 15:56:44 +02:00
|
|
|
MEMORYSTATUS ms;
|
|
|
|
|
DWORD sum;
|
|
|
|
|
ms.dwLength = sizeof(MEMORYSTATUS);
|
|
|
|
|
GlobalMemoryStatus( &ms);
|
|
|
|
|
sum = ms.dwAvailPhys + ms.dwAvailPageFile;
|
|
|
|
|
return (size_t) sum;
|
2002-01-03 23:44:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
char *startdata;
|
|
|
|
|
char *enddata;
|
|
|
|
|
|
2002-01-03 23:44:21 +01:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_rlimits(void)
|
|
|
|
|
{
|
2005-05-22 22:39:07 +02:00
|
|
|
# ifdef HAVE__MEMAVL /* hvogt */
|
2002-01-03 23:44:21 +01:00
|
|
|
mem_avail = _memavl( );
|
|
|
|
|
# else
|
2000-04-27 22:03:57 +02:00
|
|
|
startdata = (char *) baseaddr( );
|
|
|
|
|
enddata = sbrk(0);
|
2002-01-03 23:44:21 +01:00
|
|
|
# endif
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_time(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_GETRUSAGE
|
|
|
|
|
#else
|
|
|
|
|
# ifdef HAVE_TIMES
|
|
|
|
|
# else
|
|
|
|
|
# ifdef HAVE_FTIME
|
|
|
|
|
ftime(&timebegin);
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
com_rusage(wordlist *wl)
|
|
|
|
|
{
|
2000-10-26 19:02:12 +02:00
|
|
|
char* copyword;
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Fill in the SPICE accounting structure... */
|
|
|
|
|
|
|
|
|
|
if (wl && (eq(wl->wl_word, "everything") || eq(wl->wl_word, "all"))) {
|
|
|
|
|
printres((char *) NULL);
|
|
|
|
|
} else if (wl) {
|
|
|
|
|
for (; wl; wl = wl->wl_next) {
|
2000-10-26 19:02:12 +02:00
|
|
|
/* printres(cp_unquote(wl->wl_word)); DG: bad, memory leak*/
|
|
|
|
|
copyword=cp_unquote(wl->wl_word);/*DG*/
|
|
|
|
|
printres(copyword);
|
|
|
|
|
tfree(copyword);
|
2000-04-27 22:03:57 +02:00
|
|
|
if (wl->wl_next)
|
|
|
|
|
(void) putc('\n', cp_out);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
printres("cputime");
|
|
|
|
|
(void) putc('\n', cp_out);
|
|
|
|
|
printres("totalcputime");
|
|
|
|
|
(void) putc('\n', cp_out);
|
|
|
|
|
printres("space");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
/* Find out if the user is approaching his maximum data size.
|
|
|
|
|
If usage is withing 90% of total available then a warning message is sent
|
|
|
|
|
to the error stream (cp_err) */
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
|
|
|
|
ft_ckspace(void)
|
|
|
|
|
{
|
2007-11-28 18:29:28 +01:00
|
|
|
size_t usage, limit;
|
2002-01-03 23:44:21 +01:00
|
|
|
|
|
|
|
|
#ifdef HAVE__MEMAVL
|
2005-09-06 23:19:58 +02:00
|
|
|
size_t mem_avail_now;
|
2002-01-03 23:44:21 +01:00
|
|
|
|
2005-09-06 23:19:58 +02:00
|
|
|
mem_avail_now = _memavl( );
|
|
|
|
|
usage = mem_avail - mem_avail_now;
|
|
|
|
|
limit = mem_avail;
|
|
|
|
|
#else /* HAVE__MEMAVL */
|
2005-10-15 15:56:44 +02:00
|
|
|
static size_t old_usage = 0;
|
2000-04-27 22:03:57 +02:00
|
|
|
char *hi;
|
|
|
|
|
|
|
|
|
|
# ifdef HAVE_GETRLIMIT
|
|
|
|
|
struct rlimit rld;
|
|
|
|
|
getrlimit(RLIMIT_DATA, &rld);
|
|
|
|
|
if (rld.rlim_cur == RLIM_INFINITY)
|
|
|
|
|
return;
|
|
|
|
|
limit = rld.rlim_cur - (enddata - startdata); /* rlim_max not used */
|
2005-09-06 23:19:58 +02:00
|
|
|
# else /* HAVE_GETRLIMIT */
|
2000-04-27 22:03:57 +02:00
|
|
|
/* SYSVRLIMIT */
|
|
|
|
|
limit = ulimit(3, 0L) - (enddata - startdata);
|
2005-09-06 23:19:58 +02:00
|
|
|
# endif /* HAVE_GETRLIMIT */
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
hi=sbrk(0);
|
2005-10-15 15:56:44 +02:00
|
|
|
usage = (size_t) (hi - enddata);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (limit < 0)
|
|
|
|
|
return; /* what else do you do? */
|
|
|
|
|
|
|
|
|
|
if (usage <= old_usage)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
old_usage = usage;
|
2005-09-06 23:19:58 +02:00
|
|
|
#endif /* HAVE__MEMAVL */
|
2002-01-03 23:44:21 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (usage > limit * 0.9) {
|
|
|
|
|
fprintf(cp_err, "Warning - approaching max data size: ");
|
2005-10-15 15:56:44 +02:00
|
|
|
fprintf(cp_err, "current size = ");
|
|
|
|
|
fprintmem(cp_err, usage);
|
|
|
|
|
fprintf(cp_err,", limit = ");
|
|
|
|
|
fprintmem(cp_err, limit);
|
|
|
|
|
fprintf(cp_err,"\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print out one piece of resource usage information. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
printres(char *name)
|
|
|
|
|
{
|
2003-08-11 22:53:33 +02:00
|
|
|
#ifdef CIDER
|
|
|
|
|
char *paramname = NULL;
|
|
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
bool yy = FALSE;
|
|
|
|
|
static long lastsec = 0, lastusec = 0;
|
|
|
|
|
struct variable *v;
|
|
|
|
|
char *cpu_elapsed;
|
|
|
|
|
|
2005-06-30 16:38:21 +02:00
|
|
|
#ifdef XSPICE
|
|
|
|
|
/* gtri - add - 12/12/90 - wbk - a temp for testing purposes */
|
|
|
|
|
double ipc_test;
|
|
|
|
|
/* gtri - end - 12/12/90 - wbk - */
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!name || eq(name, "totalcputime") || eq(name, "cputime")) {
|
|
|
|
|
int total, totalu;
|
|
|
|
|
|
|
|
|
|
#ifdef ipsc
|
|
|
|
|
# define NO_RUDATA
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
# ifdef HAVE_GETRUSAGE
|
|
|
|
|
struct rusage ruse;
|
|
|
|
|
(void) getrusage(RUSAGE_SELF, &ruse);
|
|
|
|
|
total = ruse.ru_utime.tv_sec + ruse.ru_stime.tv_sec;
|
|
|
|
|
totalu = (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec) / 1000;
|
|
|
|
|
cpu_elapsed = "CPU";
|
|
|
|
|
# else
|
|
|
|
|
# ifdef HAVE_TIMES
|
|
|
|
|
struct tms ruse;
|
|
|
|
|
realt = times(&ruse);
|
|
|
|
|
total = (ruse.tms_utime + ruse.tms_stime)/ HZ;
|
|
|
|
|
totalu = (ruse.tms_utime + ruse.tms_utime) * 1000 / HZ;
|
|
|
|
|
cpu_elapsed = "CPU";
|
|
|
|
|
# else
|
|
|
|
|
# ifdef HAVE_FTIME
|
|
|
|
|
struct timeb timenow;
|
2005-05-22 22:39:07 +02:00
|
|
|
/* int sec, msec; sjb */
|
2000-04-27 22:03:57 +02:00
|
|
|
ftime(&timenow);
|
|
|
|
|
timediff(&timenow, &timebegin, &total, &totalu);
|
2005-05-22 22:39:07 +02:00
|
|
|
/* totalu /= 1000; hvogt */
|
2000-04-27 22:03:57 +02:00
|
|
|
cpu_elapsed = "elapsed";
|
|
|
|
|
# else
|
|
|
|
|
# define NO_RUDATA
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef NO_RUDATA
|
|
|
|
|
if (!name || eq(name, "totalcputime")) {
|
|
|
|
|
total += totalu / 1000;
|
|
|
|
|
totalu %= 1000;
|
|
|
|
|
fprintf(cp_out, "Total %s time: %u.%03u seconds.\n",
|
|
|
|
|
cpu_elapsed, total, totalu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!name || eq(name, "cputime")) {
|
|
|
|
|
lastusec = totalu - lastusec;
|
|
|
|
|
lastsec = total - lastsec;
|
|
|
|
|
while (lastusec < 0) {
|
|
|
|
|
lastusec += 1000;
|
|
|
|
|
lastsec -= 1;
|
|
|
|
|
}
|
|
|
|
|
while (lastusec > 1000) {
|
|
|
|
|
lastusec -= 1000;
|
|
|
|
|
lastsec += 1;
|
|
|
|
|
}
|
2002-01-03 23:44:21 +01:00
|
|
|
#ifndef HAVE__MEMAVL
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_out, "%s time since last call: %lu.%03lu seconds.\n",
|
|
|
|
|
cpu_elapsed, lastsec, lastusec);
|
2002-01-03 23:44:21 +01:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
lastsec = total;
|
|
|
|
|
lastusec = totalu;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-30 16:38:21 +02:00
|
|
|
#ifdef XSPICE
|
|
|
|
|
/* gtri - add - 12/12/90 - wbk - record cpu time used for ipc */
|
|
|
|
|
g_ipc.cpu_time = lastsec;
|
|
|
|
|
ipc_test = lastsec;
|
|
|
|
|
g_ipc.cpu_time = (double) lastusec;
|
|
|
|
|
g_ipc.cpu_time /= 1.0e6;
|
|
|
|
|
g_ipc.cpu_time += (double) lastsec;
|
|
|
|
|
/* gtri - end - 12/12/90 */
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
yy = TRUE;
|
|
|
|
|
#else
|
|
|
|
|
if (!name || eq(name, "totalcputime"))
|
|
|
|
|
fprintf(cp_out, "Total CPU time: ??.??? seconds.\n");
|
|
|
|
|
if (!name || eq(name, "cputime"))
|
|
|
|
|
fprintf(cp_out, "CPU time since last call: ??.??? seconds.\n");
|
|
|
|
|
yy = TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!name || eq(name, "space")) {
|
2007-11-28 18:29:28 +01:00
|
|
|
size_t usage = 0, limit = 0;
|
2002-01-03 23:44:21 +01:00
|
|
|
|
|
|
|
|
#ifdef HAVE__MEMAVL
|
|
|
|
|
size_t mem_avail_now;
|
|
|
|
|
|
|
|
|
|
mem_avail_now = _memavl( );
|
|
|
|
|
usage = mem_avail - mem_avail_now;
|
|
|
|
|
limit = mem_avail;
|
2005-10-15 15:56:44 +02:00
|
|
|
#else /* HAVE__MEMAVL */
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
#ifdef ipsc
|
|
|
|
|
NXINFO cur = nxinfo, start = nxinfo_snap;
|
|
|
|
|
|
|
|
|
|
usage = cur.dataend - cur.datastart;
|
|
|
|
|
limit = start.availmem;
|
2005-10-15 15:56:44 +02:00
|
|
|
#else /* ipsc */
|
2000-04-27 22:03:57 +02:00
|
|
|
# ifdef HAVE_GETRLIMIT
|
|
|
|
|
struct rlimit rld;
|
|
|
|
|
char *hi;
|
|
|
|
|
|
|
|
|
|
getrlimit(RLIMIT_DATA, &rld);
|
|
|
|
|
limit = rld.rlim_cur - (enddata - startdata);
|
|
|
|
|
hi = sbrk(0);
|
2005-10-15 15:56:44 +02:00
|
|
|
usage = (size_t) (hi - enddata);
|
|
|
|
|
# else /* HAVE_GETRLIMIT */
|
2000-04-27 22:03:57 +02:00
|
|
|
# ifdef HAVE_ULIMIT
|
|
|
|
|
char *hi;
|
|
|
|
|
|
|
|
|
|
limit = ulimit(3, 0L) - (enddata - startdata);
|
|
|
|
|
hi = sbrk(0);
|
2005-10-15 15:56:44 +02:00
|
|
|
usage = (size_t) (hi - enddata);
|
|
|
|
|
# endif /* HAVE_ULIMIT */
|
|
|
|
|
# endif /* HAVE_GETRLIMIT */
|
|
|
|
|
#endif /* ipsc */
|
|
|
|
|
#endif /* HAVE__MEMAVL */
|
|
|
|
|
|
|
|
|
|
fprintf(cp_out, "Current dynamic memory usage = ");
|
|
|
|
|
fprintmem(cp_out, usage);
|
|
|
|
|
fprintf(cp_out, ",\n");
|
|
|
|
|
|
|
|
|
|
fprintf(cp_out, "Dynamic memory limit = ");
|
|
|
|
|
fprintmem(cp_out, limit);
|
|
|
|
|
fprintf(cp_out, ".\n");
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
yy = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!name || eq(name, "faults")) {
|
|
|
|
|
#ifdef HAVE_GETRUSAGE
|
|
|
|
|
struct rusage ruse;
|
|
|
|
|
|
|
|
|
|
(void) getrusage(RUSAGE_SELF, &ruse);
|
|
|
|
|
fprintf(cp_out,
|
|
|
|
|
"%lu page faults, %lu vol + %lu invol = %lu context switches.\n",
|
|
|
|
|
ruse.ru_majflt, ruse.ru_nvcsw, ruse.ru_nivcsw,
|
|
|
|
|
ruse.ru_nvcsw + ruse.ru_nivcsw);
|
|
|
|
|
yy = TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now get all the spice resource stuff. */
|
|
|
|
|
if (ft_curckt && ft_curckt->ci_ckt) {
|
2003-08-11 22:53:33 +02:00
|
|
|
|
|
|
|
|
#ifdef CIDER
|
|
|
|
|
/* begin cider integration */
|
2005-10-15 15:56:44 +02:00
|
|
|
if (!name || eq(name, "circuit") || eq(name, "task")) {
|
|
|
|
|
paramname = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
paramname = name;
|
|
|
|
|
}
|
|
|
|
|
v = if_getstat(ft_curckt->ci_ckt, paramname);
|
|
|
|
|
if (paramname && v) {
|
2003-08-11 22:53:33 +02:00
|
|
|
/* end cider integration */
|
|
|
|
|
#else /* ~CIDER */
|
2000-04-27 22:03:57 +02:00
|
|
|
if (name && eq(name, "task"))
|
|
|
|
|
v = if_getstat(ft_curckt->ci_ckt, NULL);
|
|
|
|
|
else
|
|
|
|
|
v = if_getstat(ft_curckt->ci_ckt, name);
|
2005-10-15 15:56:44 +02:00
|
|
|
if (name && v) {
|
2003-08-11 22:53:33 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_out, "%s = ", v->va_name);
|
|
|
|
|
wl_print(cp_varwl(v), cp_out);
|
|
|
|
|
(void) putc('\n', cp_out);
|
|
|
|
|
yy = TRUE;
|
|
|
|
|
} else if (v) {
|
|
|
|
|
(void) putc('\n', cp_out);
|
|
|
|
|
while (v) {
|
|
|
|
|
fprintf(cp_out, "%s = ", v->va_name);
|
|
|
|
|
wl_print(cp_varwl(v), cp_out);
|
|
|
|
|
(void) putc('\n', cp_out);
|
|
|
|
|
v = v->va_next;
|
|
|
|
|
}
|
|
|
|
|
yy = TRUE;
|
|
|
|
|
}
|
2003-08-11 22:53:33 +02:00
|
|
|
|
|
|
|
|
#ifdef CIDER
|
|
|
|
|
/* begin cider integration */
|
|
|
|
|
/* Now print out interesting stuff about numerical devices. */
|
|
|
|
|
if (!name || eq(name, "devices")) {
|
2005-09-06 23:19:58 +02:00
|
|
|
(void) NDEVacct((CKTcircuit*)ft_curckt->ci_ckt, cp_out);
|
2003-08-11 22:53:33 +02:00
|
|
|
yy = TRUE;
|
|
|
|
|
}
|
|
|
|
|
/* end cider integration */
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!yy) {
|
|
|
|
|
fprintf(cp_err, "Note: no resource usage information for '%s',\n",
|
|
|
|
|
name);
|
|
|
|
|
fprintf(cp_err, "\tor no active circuit available\n");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
/* Print to stream the given memory size in a human friendly format */
|
|
|
|
|
static void
|
|
|
|
|
fprintmem(FILE* stream, size_t memory) {
|
|
|
|
|
if (memory > 1000000)
|
|
|
|
|
fprintf(stream, "%8.6f MB", memory/1000000.);
|
|
|
|
|
else if (memory > 1000)
|
|
|
|
|
fprintf(stream, "%5.3f kB", memory/1000.);
|
|
|
|
|
else
|
|
|
|
|
fprintf(stream, "%lu bytes", (unsigned long)memory);
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2007-11-28 18:29:28 +01:00
|
|
|
#ifndef HAVE__MEMAVL
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
#include <signal.h>
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* baseaddr( ) returns the base address of the data segment on most Unix
|
|
|
|
|
* systems. It's an ugly hack for info that should be provided by the OS.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Does anyone use a pagesize < 256 bytes?? I'll bet not;
|
|
|
|
|
* too small doesn't hurt
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define LOG2_PAGESIZE 8
|
|
|
|
|
|
2005-05-21 14:24:09 +02:00
|
|
|
static JMP_BUF env;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
static RETSIGTYPE
|
|
|
|
|
fault(void)
|
|
|
|
|
{
|
2005-10-15 15:56:44 +02:00
|
|
|
signal(SIGSEGV, (SIGNAL_FUNCTION) fault); /* SysV style */
|
|
|
|
|
LONGJMP(env, 1);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
baseaddr(void)
|
|
|
|
|
{
|
2005-05-21 14:24:09 +02:00
|
|
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(HAS_WINDOWS) || defined(__APPLE__)
|
2005-10-15 15:56:44 +02:00
|
|
|
return 0;
|
2005-05-21 14:24:09 +02:00
|
|
|
#else
|
2005-10-15 15:56:44 +02:00
|
|
|
char *low, *high, *at;
|
|
|
|
|
long x;
|
|
|
|
|
RETSIGTYPE (*orig_signal)( );
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
if (getenv("SPICE_NO_DATASEG_CHECK"))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
low = 0;
|
|
|
|
|
high = (char *) ((unsigned long) sbrk(0) & ~((1 << LOG2_PAGESIZE) - 1));
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
orig_signal = signal(SIGSEGV, (SIGNAL_FUNCTION) fault);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
do {
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
at = (char *) ((((long)low >> LOG2_PAGESIZE)
|
|
|
|
|
+ ((long)high >> LOG2_PAGESIZE))
|
|
|
|
|
<< (LOG2_PAGESIZE - 1));
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
if (at == low || at == high) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
if (SETJMP(env, 1)) {
|
|
|
|
|
low = at;
|
|
|
|
|
continue;
|
|
|
|
|
} else
|
|
|
|
|
x = *at;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
if (SETJMP(env, 1)) {
|
|
|
|
|
low = at;
|
|
|
|
|
continue;
|
|
|
|
|
} else
|
|
|
|
|
*at = x;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
high = at;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
} while (1);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-10-15 15:56:44 +02:00
|
|
|
(void) signal(SIGSEGV, (SIGNAL_FUNCTION) orig_signal);
|
|
|
|
|
return (void *) high;
|
2005-05-21 14:24:09 +02:00
|
|
|
|
|
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2007-11-28 18:29:28 +01:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
# ifdef notdef
|
|
|
|
|
main( )
|
|
|
|
|
{
|
2005-10-15 15:56:44 +02:00
|
|
|
printf("testing\n");
|
|
|
|
|
printf("baseaddr: %#8x topaddr: %#8x\n", baseaddr( ), sbrk(0));
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
# endif
|
|
|
|
|
|