212 lines
4.5 KiB
C
Executable File
212 lines
4.5 KiB
C
Executable File
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
|
||
/* All Rights Reserved */
|
||
|
||
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
||
/* The copyright notice above does not evidence any */
|
||
/* actual or intended publication of such source code. */
|
||
|
||
#ident "@(#)memory.c 1.8 93/03/07 SMI" /* SVr4.0 1.1 */
|
||
|
||
/*LINTLIBRARY*/
|
||
|
||
/*
|
||
* memory.c
|
||
* sysmem() Get the amount of memory on the system
|
||
* asysmem() Get the amount of available memory on the system
|
||
*/
|
||
|
||
/*
|
||
* G L O B A L D E F I N I T I O N S
|
||
* - Header files referenced
|
||
* - Global functions referenced
|
||
*/
|
||
|
||
|
||
/*
|
||
* Header files included:
|
||
* <sys/types.h> Data types known to the kernel
|
||
* <nlist.h> Definitions for Sun symbol table entries
|
||
* <sys/sysinfo.h> Internal Kernel definitions
|
||
* <sys/param.h> Internal Kernel Parameters
|
||
* <sys/sysmacros.h> Internal Kernel Macros
|
||
* <fcntl.h> File control definitions
|
||
* <unistd.h> UNIX Standard definitions
|
||
*/
|
||
|
||
#include <sys/types.h>
|
||
#include <nlist.h>
|
||
#include <sys/sysinfo.h>
|
||
#include <sys/param.h>
|
||
#include <sys/sysmacros.h>
|
||
#include <fcntl.h>
|
||
#include <unistd.h>
|
||
#include <string.h>
|
||
#include <values.h>
|
||
|
||
/*
|
||
* External references
|
||
* malloc() Allocate a block of main memory
|
||
* free() Free malloc()ed memory
|
||
* lseek() Seek an open file
|
||
* read() Read from an open file
|
||
* close() Close an open file
|
||
*/
|
||
|
||
extern char *malloc();
|
||
extern void free();
|
||
extern long lseek();
|
||
extern int read();
|
||
extern int close();
|
||
|
||
/*
|
||
* L O C A L D E F I N I T I O N S
|
||
* - Local constants
|
||
* - Local function definitions
|
||
* - Static data
|
||
*/
|
||
|
||
/*
|
||
* Local Constants
|
||
* TRUE Boolean value, true
|
||
* FALSE Boolean value, false
|
||
* NULL No such address (nil)
|
||
*/
|
||
|
||
#ifndef TRUE
|
||
#define TRUE (1)
|
||
#endif
|
||
|
||
#ifndef FALSE
|
||
#define FALSE (0)
|
||
#endif
|
||
|
||
#ifndef NULL
|
||
#define NULL (0)
|
||
#endif
|
||
|
||
#define PHYSMEM 0
|
||
#define FREEMEM 1
|
||
#define MEG4 0x400000
|
||
|
||
static struct nlist nl[] = {
|
||
#ifndef SUNOS41
|
||
{"physmem", 0, 0, 0, 2, 0},
|
||
{"freemem", 0, 0, 0, 2, 0},
|
||
#else
|
||
{"physmem", 0, 0, 0, 0},
|
||
{"freemem", 0, 0, 0, 0},
|
||
#endif
|
||
{NULL}
|
||
};
|
||
|
||
static long sunmem();
|
||
|
||
|
||
/*
|
||
* Local Macros
|
||
* strend(p) Find the end of the string pointed to by "p"
|
||
*/
|
||
|
||
#define strend(p) strrchr(p,'\0')
|
||
|
||
/*
|
||
* sysmem()
|
||
*
|
||
* Return the amount of memory configured on the system.
|
||
*
|
||
* On a Sun, this is the value of "physmem" read from the
|
||
* kernel symbol table, converted to number of bytes.
|
||
*
|
||
* Arguments: None
|
||
*
|
||
* Returns: long
|
||
* On a Sun, whatever is read from "physmem" symbol table entry,
|
||
* converted to number of bytes.
|
||
*/
|
||
|
||
long
|
||
sysmem()
|
||
{
|
||
long physmem; /* total amount of physical memory, in bytes */
|
||
int i;
|
||
|
||
if ((physmem = (long) sunmem(PHYSMEM)) == (long)-1 )
|
||
return ((long)-1);
|
||
|
||
/*
|
||
* The value read from kernel memory does not include pages
|
||
* hidden by the monitor and debugger, and so looks like there's
|
||
* a memory loss. That loss is well within 4Mg, so we should
|
||
* be able to round up to the next multiple of 4Mg and assume
|
||
* it to be amount of physical memory in the system. If that
|
||
* would overflow a long, return -1.
|
||
*/
|
||
if (physmem > (MAXLONG & ~(MEG4 - 1)))
|
||
return (-1);
|
||
|
||
physmem = (physmem + (MEG4 - 1)) & ~(MEG4 - 1);
|
||
|
||
return ((long)physmem);
|
||
}
|
||
|
||
/*
|
||
* int asysmem()
|
||
*
|
||
* This function returns the amount of available memory on the system.
|
||
* This is defined by
|
||
*
|
||
* Arguments: None
|
||
*
|
||
* Returns: long
|
||
* The amount of available memory or -1 with "errno" set if the value
|
||
* is not available.
|
||
* On a Sun, this is the value of "freemem" read from the
|
||
* kernel symbol table, converted to number of bytes.
|
||
*/
|
||
|
||
long
|
||
asysmem()
|
||
{
|
||
return ((long) sunmem(FREEMEM));
|
||
}
|
||
|
||
/*
|
||
* The SUN way of accessing amounts of kernel memory
|
||
*/
|
||
static long
|
||
sunmem(index)
|
||
int index; /* index into global nl array for desired symbol */
|
||
{
|
||
long rtnval; /* amount of memory, in bytes */
|
||
long memsize; /* amount of memory, in pages */
|
||
long pagesize; /* size of page, in bytes */
|
||
int memfd;
|
||
|
||
/* Check out namelist and memory files. */
|
||
if (nlist("/dev/ksyms", nl) != 0)
|
||
return ((long)-1);
|
||
|
||
if (nl[index].n_value == 0)
|
||
return ((long)-1);
|
||
|
||
/* Open kernel memory */
|
||
rtnval = -1;
|
||
if ((memfd = open("/dev/kmem", O_RDONLY, 0)) > 0) {
|
||
|
||
if ((lseek(memfd, (long)nl[index].n_value, SEEK_SET) != -1) &&
|
||
(read(memfd, &memsize, sizeof(memsize)) == sizeof(memsize))) {
|
||
pagesize = sysconf(_SC_PAGESIZE);
|
||
/* check for sysconf error or overflow */
|
||
if (pagesize != -1 && memsize <= (MAXLONG / pagesize))
|
||
rtnval = memsize * pagesize;
|
||
}
|
||
|
||
/* Close kernel memory */
|
||
(void) close(memfd);
|
||
|
||
} /* If successfully opened /dev/kmem */
|
||
|
||
/* Fini */
|
||
return(rtnval);
|
||
}
|