mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Added memstat, a program for displaying memory usage.
This commit is contained in:
parent
f45def4a68
commit
9152443816
7 changed files with 111 additions and 2 deletions
|
@ -170,7 +170,9 @@ int usleep(useconds_t useconds);
|
||||||
#endif
|
#endif
|
||||||
int unlink(const char*);
|
int unlink(const char*);
|
||||||
ssize_t write(int, const void*, size_t);
|
ssize_t write(int, const void*, size_t);
|
||||||
|
|
||||||
#ifdef SORTIX_EXTENSIONS
|
#ifdef SORTIX_EXTENSIONS
|
||||||
|
int memstat(size_t* memused, size_t* memtotal);
|
||||||
int writeall(int fd, const void* buffer, size_t len);
|
int writeall(int fd, const void* buffer, size_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,11 @@
|
||||||
|
|
||||||
#include <sortix/memorymanagement.h>
|
#include <sortix/memorymanagement.h>
|
||||||
#include <sortix/panic.h>
|
#include <sortix/panic.h>
|
||||||
|
|
||||||
|
#else // !SORTIX_KERNEL
|
||||||
|
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IsGoodChunkPosition(Chunk) ((uintptr_t) Wilderness + WildernessSize <= (uintptr_t) (Chunk) && (uintptr_t) (Chunk) <= (uintptr_t) HeapStart)
|
#define IsGoodChunkPosition(Chunk) ((uintptr_t) Wilderness + WildernessSize <= (uintptr_t) (Chunk) && (uintptr_t) (Chunk) <= (uintptr_t) HeapStart)
|
||||||
|
@ -72,6 +77,15 @@ namespace Maxsi
|
||||||
|
|
||||||
namespace Memory
|
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
|
// 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
|
// chunk's header or footer, which means the program has malfunctioned
|
||||||
// and ought to be terminated.
|
// and ought to be terminated.
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace Sortix
|
||||||
bool MapUser(addr_t physical, addr_t mapto);
|
bool MapUser(addr_t physical, addr_t mapto);
|
||||||
addr_t UnmapKernel(addr_t mapto);
|
addr_t UnmapKernel(addr_t mapto);
|
||||||
addr_t UnmapUser(addr_t mapto);
|
addr_t UnmapUser(addr_t mapto);
|
||||||
|
void Statistics(size_t* amountused, size_t* totalmem);
|
||||||
|
|
||||||
#if defined(PLATFORM_X86)
|
#if defined(PLATFORM_X86)
|
||||||
const addr_t HEAPLOWER = 0x80000000UL;
|
const addr_t HEAPLOWER = 0x80000000UL;
|
||||||
|
|
|
@ -57,7 +57,8 @@
|
||||||
#define SYSCALL_REGISTER_SIGNAL_HANDLER 29
|
#define SYSCALL_REGISTER_SIGNAL_HANDLER 29
|
||||||
#define SYSCALL_SIGRETURN 30
|
#define SYSCALL_SIGRETURN 30
|
||||||
#define SYSCALL_KILL 31
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,11 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "../memorymanagement.h"
|
#include "../memorymanagement.h"
|
||||||
#include "memorymanagement.h"
|
#include "memorymanagement.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
const addr_t KERNELEND = 0x200000UL;
|
const addr_t KERNELEND = 0x400000UL;
|
||||||
|
|
||||||
namespace Page
|
namespace Page
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,8 @@ namespace Sortix
|
||||||
size_t pagesnotonstack;
|
size_t pagesnotonstack;
|
||||||
size_t stackused;
|
size_t stackused;
|
||||||
size_t stacklength;
|
size_t stacklength;
|
||||||
|
size_t totalmem;
|
||||||
|
size_t pagesallocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
|
@ -47,10 +50,15 @@ namespace Sortix
|
||||||
|
|
||||||
void InitCPU();
|
void InitCPU();
|
||||||
void AllocateKernelPMLs();
|
void AllocateKernelPMLs();
|
||||||
|
int SysMemStat(size_t* memused, size_t* memtotal);
|
||||||
|
|
||||||
void Init(multiboot_info_t* bootinfo)
|
void Init(multiboot_info_t* bootinfo)
|
||||||
{
|
{
|
||||||
Page::pagesnotonstack = 0;
|
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 ) )
|
if ( !( bootinfo->flags & MULTIBOOT_INFO_MEM_MAP ) )
|
||||||
{
|
{
|
||||||
|
@ -84,6 +92,9 @@ namespace Sortix
|
||||||
if ( 0xFFFFFFFFULL < mmap->addr + mmap->len ) { length = 0x100000000ULL - mmap->addr; }
|
if ( 0xFFFFFFFFULL < mmap->addr + mmap->len ) { length = 0x100000000ULL - mmap->addr; }
|
||||||
#endif
|
#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.
|
// Detect if this memory is completely covered by the kernel.
|
||||||
if ( base + length <= KERNELEND ) { continue; }
|
if ( base + length <= KERNELEND ) { continue; }
|
||||||
|
|
||||||
|
@ -95,6 +106,8 @@ namespace Sortix
|
||||||
}
|
}
|
||||||
|
|
||||||
Page::InitPushRegion(base, length);
|
Page::InitPushRegion(base, length);
|
||||||
|
|
||||||
|
Syscall::Register(SYSCALL_MEMSTAT, (void*) SysMemStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the physical allocator couldn't handle the vast amount of
|
// If the physical allocator couldn't handle the vast amount of
|
||||||
|
@ -110,6 +123,23 @@ namespace Sortix
|
||||||
AllocateKernelPMLs();
|
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
|
// Prepare the non-forkable kernel PMLs such that forking the kernel
|
||||||
// address space will always keep the kernel mapped.
|
// address space will always keep the kernel mapped.
|
||||||
void AllocateKernelPMLs()
|
void AllocateKernelPMLs()
|
||||||
|
@ -188,12 +218,15 @@ namespace Sortix
|
||||||
// TODO: Set out of memory errno here!
|
// TODO: Set out of memory errno here!
|
||||||
if ( unlikely(stackused == 0) ) { return 0; }
|
if ( unlikely(stackused == 0) ) { return 0; }
|
||||||
|
|
||||||
|
pagesallocated++;
|
||||||
|
|
||||||
return STACK[--stackused];
|
return STACK[--stackused];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Put(addr_t page)
|
void Put(addr_t page)
|
||||||
{
|
{
|
||||||
ASSERT(stackused < MAXSTACKLENGTH);
|
ASSERT(stackused < MAXSTACKLENGTH);
|
||||||
|
pagesallocated--;
|
||||||
STACK[stackused++] = page;
|
STACK[stackused++] = page;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ mxsh \
|
||||||
clear \
|
clear \
|
||||||
ls \
|
ls \
|
||||||
help \
|
help \
|
||||||
|
memstat \
|
||||||
uname \
|
uname \
|
||||||
idle \
|
idle \
|
||||||
editor \
|
editor \
|
||||||
|
|
57
utils/memstat.cpp
Normal file
57
utils/memstat.cpp
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue