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 uptime(uintmax_t* usecssinceboot);
|
||||
int writeall(int fd, const void* buffer, size_t len);
|
||||
void* sbrk(intptr_t increment);
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
|
|
@ -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!
|
||||
}
|
||||
|
||||
size_t GetHeapMaxSize()
|
||||
{
|
||||
#ifdef SORTIX_KERNEL
|
||||
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)
|
||||
{
|
||||
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); };
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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) )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
Loading…
Reference in a new issue