Added memstat, a program for displaying memory usage.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-26 20:14:57 +01:00
parent f45def4a68
commit 9152443816
7 changed files with 111 additions and 2 deletions

View File

@ -170,7 +170,9 @@ int usleep(useconds_t useconds);
#endif
int unlink(const char*);
ssize_t write(int, const void*, size_t);
#ifdef SORTIX_EXTENSIONS
int memstat(size_t* memused, size_t* memtotal);
int writeall(int fd, const void* buffer, size_t len);
#endif

View File

@ -34,6 +34,11 @@
#include <sortix/memorymanagement.h>
#include <sortix/panic.h>
#else // !SORTIX_KERNEL
#include "syscall.h"
#endif
#define IsGoodChunkPosition(Chunk) ((uintptr_t) Wilderness + WildernessSize <= (uintptr_t) (Chunk) && (uintptr_t) (Chunk) <= (uintptr_t) HeapStart)
@ -72,6 +77,15 @@ namespace Maxsi
namespace Memory
{
#ifndef SORTIX_KERNEL
DEFN_SYSCALL2(int, SysMemStat, 32, size_t*, size_t*);
extern "C" int memstat(size_t* memused, size_t* memtotal)
{
return SysMemStat(memused, memtotal);
}
#endif
// This magic word is useful to see if the program has written into the
// chunk's header or footer, which means the program has malfunctioned
// and ought to be terminated.

View File

@ -57,6 +57,7 @@ namespace Sortix
bool MapUser(addr_t physical, addr_t mapto);
addr_t UnmapKernel(addr_t mapto);
addr_t UnmapUser(addr_t mapto);
void Statistics(size_t* amountused, size_t* totalmem);
#if defined(PLATFORM_X86)
const addr_t HEAPLOWER = 0x80000000UL;

View File

@ -57,7 +57,8 @@
#define SYSCALL_REGISTER_SIGNAL_HANDLER 29
#define SYSCALL_SIGRETURN 30
#define SYSCALL_KILL 31
#define SYSCALL_MAX_NUM 32 /* index of highest constant + 1 */
#define SYSCALL_MEMSTAT 32
#define SYSCALL_MAX_NUM 33 /* index of highest constant + 1 */
#endif

View File

@ -28,10 +28,11 @@
#include "panic.h"
#include "../memorymanagement.h"
#include "memorymanagement.h"
#include "syscall.h"
namespace Sortix
{
const addr_t KERNELEND = 0x200000UL;
const addr_t KERNELEND = 0x400000UL;
namespace Page
{
@ -39,6 +40,8 @@ namespace Sortix
size_t pagesnotonstack;
size_t stackused;
size_t stacklength;
size_t totalmem;
size_t pagesallocated;
}
namespace Memory
@ -47,10 +50,15 @@ namespace Sortix
void InitCPU();
void AllocateKernelPMLs();
int SysMemStat(size_t* memused, size_t* memtotal);
void Init(multiboot_info_t* bootinfo)
{
Page::pagesnotonstack = 0;
Page::totalmem = 0;
// The first mebibytes are reserved for use by the kernel.
Page::pagesallocated = KERNELEND >> 12UL;
if ( !( bootinfo->flags & MULTIBOOT_INFO_MEM_MAP ) )
{
@ -84,6 +92,9 @@ namespace Sortix
if ( 0xFFFFFFFFULL < mmap->addr + mmap->len ) { length = 0x100000000ULL - mmap->addr; }
#endif
// Count the amount of usable RAM (even if reserved for kernel).
Page::totalmem += length;
// Detect if this memory is completely covered by the kernel.
if ( base + length <= KERNELEND ) { continue; }
@ -95,6 +106,8 @@ namespace Sortix
}
Page::InitPushRegion(base, length);
Syscall::Register(SYSCALL_MEMSTAT, (void*) SysMemStat);
}
// If the physical allocator couldn't handle the vast amount of
@ -110,6 +123,23 @@ namespace Sortix
AllocateKernelPMLs();
}
void Statistics(size_t* amountused, size_t* totalmem)
{
if ( amountused ) { *amountused = Page::pagesallocated << 12Ul; }
if ( totalmem ) { *totalmem = Page::totalmem; }
}
int SysMemStat(size_t* memused, size_t* memtotal)
{
size_t used;
size_t total;
Statistics(&used, &total);
// TODO: Check if legal user-space buffers!
*memused = used;
*memtotal = total;
return 0;
}
// Prepare the non-forkable kernel PMLs such that forking the kernel
// address space will always keep the kernel mapped.
void AllocateKernelPMLs()
@ -188,12 +218,15 @@ namespace Sortix
// TODO: Set out of memory errno here!
if ( unlikely(stackused == 0) ) { return 0; }
pagesallocated++;
return STACK[--stackused];
}
void Put(addr_t page)
{
ASSERT(stackused < MAXSTACKLENGTH);
pagesallocated--;
STACK[stackused++] = page;
}
}

View File

@ -14,6 +14,7 @@ mxsh \
clear \
ls \
help \
memstat \
uname \
idle \
editor \

57
utils/memstat.cpp Normal file
View File

@ -0,0 +1,57 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void printbytes(unsigned long long bytes)
{
const unsigned BYTES = 0;
const unsigned KIBI = 1;
const unsigned MEBI = 2;
const unsigned GIBI = 3;
const unsigned TEBI = 4;
const unsigned PEBI = 5;
const unsigned EXBI = 6;
unsigned unit = BYTES;
if ( (bytes >> 10) & 1023 ) { unit = KIBI; }
if ( (bytes >> 20) & 1023 ) { unit = MEBI; }
if ( (bytes >> 30) & 1023 ) { unit = GIBI; }
if ( (bytes >> 40) & 1023 ) { unit = TEBI; }
if ( (bytes >> 50) & 1023 ) { unit = PEBI; }
if ( (bytes >> 60) & 1023 ) { unit = EXBI; }
switch ( unit )
{
case EXBI:
printf("%u ZiB ", (bytes >> 60) & 1023);
case PEBI:
printf("%u PiB ", (bytes >> 50) & 1023);
case TEBI:
printf("%u TiB ", (bytes >> 40) & 1023);
case GIBI:
printf("%u GiB ", (bytes >> 30) & 1023);
case MEBI:
printf("%u MiB ", (bytes >> 20) & 1023);
case KIBI:
printf("%u KiB", (bytes >> 10) & 1023);
break;
case BYTES:
printf("%u B", (bytes >> 0) & 1023);
}
}
int main(int argc, char* argv[])
{
size_t memused = 0;
size_t memtotal = 0;
if ( memstat(&memused, &memtotal) ) { perror("memstat"); return 1; }
printf("memory usage: ");
printbytes(memused);
printf(" free / ");
printbytes(memtotal);
unsigned percent = ((unsigned long long) memused * 100ULL ) / memtotal;
printf(" total (%u%s)\n", percent, "%");
return 0;
}