Added user-space memory allocation.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-12-16 13:24:49 +01:00
parent fecaf6b43f
commit acf1eebc98
10 changed files with 114 additions and 24 deletions

View File

@ -179,6 +179,7 @@ ssize_t write(int, const void*, size_t);
int memstat(size_t* memused, size_t* memtotal);
int uptime(uintmax_t* usecssinceboot);
int writeall(int fd, const void* buffer, size_t len);
void* sbrk(intptr_t increment);
#endif
__END_DECLS

View File

@ -30,6 +30,10 @@
#define HEAP_GROWS_DOWNWARDS
#endif
#ifndef SORTIX_KERNEL
#include <unistd.h>
#endif
#define PARANOIA 1
#ifdef SORTIX_KERNEL
@ -59,23 +63,19 @@ namespace Maxsi
const size_t PAGESIZE = 4UL * 1024UL; // 4 KiB
const size_t NUMBINS = 8UL * sizeof(size_t);
extern addr_t wilderness;
#ifdef SORTIX_KERNEL
addr_t GetHeapStart()
{
#ifdef SORTIX_KERNEL
return Sortix::Memory::HEAPUPPER;
#endif
return 0; // TODO: Not implemented in User-Space yet!
return Sortix::Memory::HEAPUPPER;
}
size_t GetHeapMaxSize()
{
#ifdef SORTIX_KERNEL
return Sortix::Memory::HEAPUPPER - Sortix::Memory::HEAPLOWER;
#endif
return 0; // TODO: Not implemented in User-Space yet!
return Sortix::Memory::HEAPUPPER - Sortix::Memory::HEAPLOWER;
}
#ifdef SORTIX_KERNEL
void FreeMemory(addr_t where, size_t bytes)
{
ASSERT( (bytes & (PAGESIZE-1UL)) == 0 );
@ -118,15 +118,40 @@ namespace Maxsi
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);
return false;
// TODO: A bit of a hack!
return SIZE_MAX;
}
bool ExtendHeap(size_t bytesneeded)
{
void* newheapend = sbrk(bytesneeded);
return newheapend != (void*) -1UL;
}
#endif
@ -395,7 +420,7 @@ namespace Maxsi
#endif
// Attempt to map pages so our wilderness grows.
if ( !AllocateMemory(newwilderness, bytesneeded) ) { return false; }
if ( !ExtendHeap(bytesneeded) ) { return false; }
wildernesssize += bytesneeded;
wilderness = newwilderness;
@ -520,7 +545,7 @@ namespace Maxsi
#ifdef HEAP_GROWS_DOWNWARDS
return heapstart <= (addr_t) chunk + chunk->size;
#else
return (addr_t) chunk + chunk->size <= heapstart + heapsize;
return heapstart + heapsize <= (addr_t) chunk + chunk->size;
#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); };

View File

@ -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 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

View File

@ -27,6 +27,7 @@
#include "signal.h"
#include "string.h"
#include "io.h"
#include "memory.h"
namespace Maxsi
{
@ -47,5 +48,8 @@ namespace Maxsi
// It's probably best to initialize the Unix signals early on.
Signal::Init();
// Initialize the dynamic heap.
Memory::Init();
}
}

View File

@ -35,11 +35,17 @@ namespace Maxsi
{
#ifndef SORTIX_KERNEL
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)
{
return SysMemStat(memused, memtotal);
}
extern "C" void* sbrk(intptr_t increment)
{
return SysSbrk(increment);
}
#endif
DUAL_FUNCTION(void*, memcpy, Copy, (void* Dest, const void* Src, size_t Length))

View File

@ -83,6 +83,7 @@ namespace Sortix
if ( segment == NULL ) { return 0; }
segment->position = mapto;
segment->size = Page::AlignUp(mapbytes);
segment->type = SEG_DATA; // TODO: BUG
if ( segment->Intersects(process->segments) )
{
@ -162,6 +163,7 @@ namespace Sortix
if ( segment == NULL ) { return 0; }
segment->position = mapto;
segment->size = Page::AlignUp(mapbytes);
segment->type = SEG_DATA; // TODO: BUG
if ( segment->Intersects(process->segments) )
{

View File

@ -691,6 +691,47 @@ namespace Sortix
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()
{
Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE);
@ -700,6 +741,7 @@ namespace Sortix
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
Syscall::Register(SYSCALL_WAIT, (void*) SysWait);
Syscall::Register(SYSCALL_REGISTER_ERRNO, (void*) SysRegisterErrno);
Syscall::Register(SYSCALL_SBRK, (void*) SysSbrk);
nextpidtoallocate = 0;

View File

@ -34,6 +34,10 @@ namespace Sortix
struct ProcessSegment;
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
{
@ -45,6 +49,7 @@ namespace Sortix
ProcessSegment* next;
addr_t position;
size_t size;
int type;
public:
bool Intersects(ProcessSegment* segments);

View File

@ -60,7 +60,8 @@
#define SYSCALL_MEMSTAT 32
#define SYSCALL_ISATTY 33
#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

View File

@ -23,6 +23,7 @@
******************************************************************************/
#include "platform.h"
#include <libmaxsi/error.h>
#include <libmaxsi/memory.h>
#include "multiboot.h"
#include "panic.h"
@ -30,6 +31,8 @@
#include "memorymanagement.h"
#include "syscall.h"
using namespace Maxsi;
namespace Sortix
{
const addr_t KERNELEND = 0x400000UL;
@ -218,8 +221,7 @@ namespace Sortix
addr_t Get()
{
// TODO: Set out of memory errno here!
if ( unlikely(stackused == 0) ) { return 0; }
if ( unlikely(stackused == 0) ) { Error::Set(ENOMEM); return 0; }
pagesallocated++;