mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Added user-space memory allocation.
This commit is contained in:
parent
fecaf6b43f
commit
acf1eebc98
10 changed files with 114 additions and 24 deletions
|
@ -179,6 +179,7 @@ ssize_t write(int, const void*, size_t);
|
||||||
int memstat(size_t* memused, size_t* memtotal);
|
int memstat(size_t* memused, size_t* memtotal);
|
||||||
int uptime(uintmax_t* usecssinceboot);
|
int uptime(uintmax_t* usecssinceboot);
|
||||||
int writeall(int fd, const void* buffer, size_t len);
|
int writeall(int fd, const void* buffer, size_t len);
|
||||||
|
void* sbrk(intptr_t increment);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
#define HEAP_GROWS_DOWNWARDS
|
#define HEAP_GROWS_DOWNWARDS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SORTIX_KERNEL
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PARANOIA 1
|
#define PARANOIA 1
|
||||||
|
|
||||||
#ifdef SORTIX_KERNEL
|
#ifdef SORTIX_KERNEL
|
||||||
|
@ -59,23 +63,19 @@ namespace Maxsi
|
||||||
const size_t PAGESIZE = 4UL * 1024UL; // 4 KiB
|
const size_t PAGESIZE = 4UL * 1024UL; // 4 KiB
|
||||||
const size_t NUMBINS = 8UL * sizeof(size_t);
|
const size_t NUMBINS = 8UL * sizeof(size_t);
|
||||||
|
|
||||||
|
extern addr_t wilderness;
|
||||||
|
|
||||||
|
#ifdef SORTIX_KERNEL
|
||||||
addr_t GetHeapStart()
|
addr_t GetHeapStart()
|
||||||
{
|
{
|
||||||
#ifdef SORTIX_KERNEL
|
return Sortix::Memory::HEAPUPPER;
|
||||||
return Sortix::Memory::HEAPUPPER;
|
|
||||||
#endif
|
|
||||||
return 0; // TODO: Not implemented in User-Space yet!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetHeapMaxSize()
|
size_t GetHeapMaxSize()
|
||||||
{
|
{
|
||||||
#ifdef SORTIX_KERNEL
|
return Sortix::Memory::HEAPUPPER - Sortix::Memory::HEAPLOWER;
|
||||||
return Sortix::Memory::HEAPUPPER - Sortix::Memory::HEAPLOWER;
|
|
||||||
#endif
|
|
||||||
return 0; // TODO: Not implemented in User-Space yet!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SORTIX_KERNEL
|
|
||||||
void FreeMemory(addr_t where, size_t bytes)
|
void FreeMemory(addr_t where, size_t bytes)
|
||||||
{
|
{
|
||||||
ASSERT( (bytes & (PAGESIZE-1UL)) == 0 );
|
ASSERT( (bytes & (PAGESIZE-1UL)) == 0 );
|
||||||
|
@ -118,15 +118,40 @@ namespace Maxsi
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void FreeMemory(addr_t where, size_t bytes)
|
bool ExtendHeap(size_t bytesneeded)
|
||||||
{
|
{
|
||||||
|
#ifdef HEAP_GROWS_DOWNWARDS
|
||||||
|
addr_t newwilderness = wilderness - bytesneeded;
|
||||||
|
#else
|
||||||
|
addr_t newwilderness = wilderness + bytesneeded;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return AllocateMemory(newwilderness, bytesneeded);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
addr_t GetHeapStart()
|
||||||
|
{
|
||||||
|
addr_t base = (addr_t) sbrk(0);
|
||||||
|
addr_t unaligned = base % ALIGNMENT;
|
||||||
|
if ( unaligned )
|
||||||
|
{
|
||||||
|
sbrk(ALIGNMENT-unaligned);
|
||||||
|
}
|
||||||
|
addr_t result = (addr_t) sbrk(0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllocateMemory(addr_t where, size_t bytes)
|
size_t GetHeapMaxSize()
|
||||||
{
|
{
|
||||||
Error::Set(ENOMEM);
|
// TODO: A bit of a hack!
|
||||||
return false;
|
return SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtendHeap(size_t bytesneeded)
|
||||||
|
{
|
||||||
|
void* newheapend = sbrk(bytesneeded);
|
||||||
|
return newheapend != (void*) -1UL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -395,7 +420,7 @@ namespace Maxsi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Attempt to map pages so our wilderness grows.
|
// Attempt to map pages so our wilderness grows.
|
||||||
if ( !AllocateMemory(newwilderness, bytesneeded) ) { return false; }
|
if ( !ExtendHeap(bytesneeded) ) { return false; }
|
||||||
|
|
||||||
wildernesssize += bytesneeded;
|
wildernesssize += bytesneeded;
|
||||||
wilderness = newwilderness;
|
wilderness = newwilderness;
|
||||||
|
@ -520,7 +545,7 @@ namespace Maxsi
|
||||||
#ifdef HEAP_GROWS_DOWNWARDS
|
#ifdef HEAP_GROWS_DOWNWARDS
|
||||||
return heapstart <= (addr_t) chunk + chunk->size;
|
return heapstart <= (addr_t) chunk + chunk->size;
|
||||||
#else
|
#else
|
||||||
return (addr_t) chunk + chunk->size <= heapstart + heapsize;
|
return heapstart + heapsize <= (addr_t) chunk + chunk->size;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,3 +644,9 @@ namespace Maxsi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* operator new(size_t Size) { return Maxsi::Memory::Allocate(Size); }
|
||||||
|
void* operator new[](size_t Size) { return Maxsi::Memory::Allocate(Size); }
|
||||||
|
void operator delete (void* Addr) { return Maxsi::Memory::Free(Addr); };
|
||||||
|
void operator delete[](void* Addr) { return Maxsi::Memory::Free(Addr); };
|
||||||
|
|
||||||
|
|
|
@ -39,15 +39,11 @@ namespace Maxsi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Placement new.
|
||||||
inline void* operator new(size_t, void* p) { return p; }
|
inline void* operator new(size_t, void* p) { return p; }
|
||||||
inline void* operator new[](size_t, void* p) { return p; }
|
inline void* operator new[](size_t, void* p) { return p; }
|
||||||
inline void operator delete (void*, void*) { };
|
inline void operator delete (void*, void*) { };
|
||||||
inline void operator delete[](void*, void*) { };
|
inline void operator delete[](void*, void*) { };
|
||||||
|
|
||||||
inline void* operator new(size_t Size) { return Maxsi::Memory::Allocate(Size); }
|
|
||||||
inline void* operator new[](size_t Size) { return Maxsi::Memory::Allocate(Size); }
|
|
||||||
inline void operator delete (void* Addr) { return Maxsi::Memory::Free(Addr); };
|
|
||||||
inline void operator delete[](void* Addr) { return Maxsi::Memory::Free(Addr); };
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
namespace Maxsi
|
namespace Maxsi
|
||||||
{
|
{
|
||||||
|
@ -47,5 +48,8 @@ namespace Maxsi
|
||||||
|
|
||||||
// It's probably best to initialize the Unix signals early on.
|
// It's probably best to initialize the Unix signals early on.
|
||||||
Signal::Init();
|
Signal::Init();
|
||||||
|
|
||||||
|
// Initialize the dynamic heap.
|
||||||
|
Memory::Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,17 @@ namespace Maxsi
|
||||||
{
|
{
|
||||||
#ifndef SORTIX_KERNEL
|
#ifndef SORTIX_KERNEL
|
||||||
DEFN_SYSCALL2(int, SysMemStat, SYSCALL_MEMSTAT, size_t*, size_t*);
|
DEFN_SYSCALL2(int, SysMemStat, SYSCALL_MEMSTAT, size_t*, size_t*);
|
||||||
|
DEFN_SYSCALL1(void*, SysSbrk, SYSCALL_SBRK, intptr_t);
|
||||||
|
|
||||||
extern "C" int memstat(size_t* memused, size_t* memtotal)
|
extern "C" int memstat(size_t* memused, size_t* memtotal)
|
||||||
{
|
{
|
||||||
return SysMemStat(memused, memtotal);
|
return SysMemStat(memused, memtotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void* sbrk(intptr_t increment)
|
||||||
|
{
|
||||||
|
return SysSbrk(increment);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DUAL_FUNCTION(void*, memcpy, Copy, (void* Dest, const void* Src, size_t Length))
|
DUAL_FUNCTION(void*, memcpy, Copy, (void* Dest, const void* Src, size_t Length))
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace Sortix
|
||||||
if ( segment == NULL ) { return 0; }
|
if ( segment == NULL ) { return 0; }
|
||||||
segment->position = mapto;
|
segment->position = mapto;
|
||||||
segment->size = Page::AlignUp(mapbytes);
|
segment->size = Page::AlignUp(mapbytes);
|
||||||
|
segment->type = SEG_DATA; // TODO: BUG
|
||||||
|
|
||||||
if ( segment->Intersects(process->segments) )
|
if ( segment->Intersects(process->segments) )
|
||||||
{
|
{
|
||||||
|
@ -162,6 +163,7 @@ namespace Sortix
|
||||||
if ( segment == NULL ) { return 0; }
|
if ( segment == NULL ) { return 0; }
|
||||||
segment->position = mapto;
|
segment->position = mapto;
|
||||||
segment->size = Page::AlignUp(mapbytes);
|
segment->size = Page::AlignUp(mapbytes);
|
||||||
|
segment->type = SEG_DATA; // TODO: BUG
|
||||||
|
|
||||||
if ( segment->Intersects(process->segments) )
|
if ( segment->Intersects(process->segments) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -691,6 +691,47 @@ namespace Sortix
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* SysSbrk(intptr_t increment)
|
||||||
|
{
|
||||||
|
Process* process = CurrentProcess();
|
||||||
|
ProcessSegment* dataseg = NULL;
|
||||||
|
for ( ProcessSegment* iter = process->segments; iter; iter = iter->next )
|
||||||
|
{
|
||||||
|
if ( !iter->type == SEG_DATA ) { continue; }
|
||||||
|
if ( dataseg && iter->position < dataseg->position ) { continue; }
|
||||||
|
dataseg = iter;
|
||||||
|
}
|
||||||
|
if ( !dataseg ) { Error::Set(ENOMEM); return (void*) -1UL; }
|
||||||
|
addr_t currentend = dataseg->position + dataseg->size;
|
||||||
|
addr_t newend = currentend + increment;
|
||||||
|
if ( newend < dataseg->position ) { Error::Set(EINVAL); return (void*) -1UL; }
|
||||||
|
if ( newend < currentend )
|
||||||
|
{
|
||||||
|
addr_t unmapfrom = Page::AlignUp(newend);
|
||||||
|
if ( unmapfrom < currentend )
|
||||||
|
{
|
||||||
|
size_t unmapbytes = Page::AlignUp(currentend - unmapfrom);
|
||||||
|
Memory::UnmapRangeUser(unmapfrom, unmapbytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( currentend < newend )
|
||||||
|
{
|
||||||
|
// TODO: HACK: Make a safer way of expanding the data segment
|
||||||
|
// without segments possibly colliding!
|
||||||
|
addr_t mapfrom = Page::AlignUp(currentend);
|
||||||
|
if ( mapfrom < newend )
|
||||||
|
{
|
||||||
|
size_t mapbytes = Page::AlignUp(newend - mapfrom);
|
||||||
|
if ( !Memory::MapRangeUser(mapfrom, mapbytes) )
|
||||||
|
{
|
||||||
|
return (void*) -1UL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataseg->size += increment;
|
||||||
|
return (void*) newend;
|
||||||
|
}
|
||||||
|
|
||||||
void Process::Init()
|
void Process::Init()
|
||||||
{
|
{
|
||||||
Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE);
|
Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE);
|
||||||
|
@ -700,6 +741,7 @@ namespace Sortix
|
||||||
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
|
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
|
||||||
Syscall::Register(SYSCALL_WAIT, (void*) SysWait);
|
Syscall::Register(SYSCALL_WAIT, (void*) SysWait);
|
||||||
Syscall::Register(SYSCALL_REGISTER_ERRNO, (void*) SysRegisterErrno);
|
Syscall::Register(SYSCALL_REGISTER_ERRNO, (void*) SysRegisterErrno);
|
||||||
|
Syscall::Register(SYSCALL_SBRK, (void*) SysSbrk);
|
||||||
|
|
||||||
nextpidtoallocate = 0;
|
nextpidtoallocate = 0;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ namespace Sortix
|
||||||
struct ProcessSegment;
|
struct ProcessSegment;
|
||||||
|
|
||||||
const size_t DEFAULT_STACK_SIZE = 64*1024;
|
const size_t DEFAULT_STACK_SIZE = 64*1024;
|
||||||
|
const int SEG_TEXT = 0;
|
||||||
|
const int SEG_DATA = 1;
|
||||||
|
const int SEG_STACK = 2;
|
||||||
|
const int SEG_OTHER = 3;
|
||||||
|
|
||||||
struct ProcessSegment
|
struct ProcessSegment
|
||||||
{
|
{
|
||||||
|
@ -45,6 +49,7 @@ namespace Sortix
|
||||||
ProcessSegment* next;
|
ProcessSegment* next;
|
||||||
addr_t position;
|
addr_t position;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
int type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Intersects(ProcessSegment* segments);
|
bool Intersects(ProcessSegment* segments);
|
||||||
|
|
|
@ -60,7 +60,8 @@
|
||||||
#define SYSCALL_MEMSTAT 32
|
#define SYSCALL_MEMSTAT 32
|
||||||
#define SYSCALL_ISATTY 33
|
#define SYSCALL_ISATTY 33
|
||||||
#define SYSCALL_UPTIME 34
|
#define SYSCALL_UPTIME 34
|
||||||
#define SYSCALL_MAX_NUM 35 /* index of highest constant + 1 */
|
#define SYSCALL_SBRK 35
|
||||||
|
#define SYSCALL_MAX_NUM 36 /* index of highest constant + 1 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include <libmaxsi/error.h>
|
||||||
#include <libmaxsi/memory.h>
|
#include <libmaxsi/memory.h>
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
@ -30,6 +31,8 @@
|
||||||
#include "memorymanagement.h"
|
#include "memorymanagement.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
|
using namespace Maxsi;
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
const addr_t KERNELEND = 0x400000UL;
|
const addr_t KERNELEND = 0x400000UL;
|
||||||
|
@ -218,8 +221,7 @@ namespace Sortix
|
||||||
|
|
||||||
addr_t Get()
|
addr_t Get()
|
||||||
{
|
{
|
||||||
// TODO: Set out of memory errno here!
|
if ( unlikely(stackused == 0) ) { Error::Set(ENOMEM); return 0; }
|
||||||
if ( unlikely(stackused == 0) ) { return 0; }
|
|
||||||
|
|
||||||
pagesallocated++;
|
pagesallocated++;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue