Use syscall instead of mmap and munmap
This commit is contained in:
parent
5cac28c093
commit
e8222123e6
@ -22,44 +22,31 @@ syscall1:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
.globl syscall2
|
// 2 parameters.
|
||||||
.type syscall2, @function
|
.globl _D5tanya3sys5linux7syscall7syscallFNbNilllZl
|
||||||
|
.type _D5tanya3sys5linux7syscall7syscallFNbNilllZl, @function
|
||||||
|
|
||||||
syscall2:
|
_D5tanya3sys5linux7syscall7syscallFNbNilllZl:
|
||||||
// Store registers.
|
movq %rdx, %rax
|
||||||
movq %rdi, %r8
|
|
||||||
|
|
||||||
movq %rdx, %rax // Syscall number.
|
|
||||||
|
|
||||||
// Syscall arguments.
|
|
||||||
movq %rsi, %rdi
|
|
||||||
movq %r8, %rsi
|
|
||||||
|
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
// Restore registers.
|
|
||||||
movq %rdi, %rsi
|
|
||||||
movq %r8, %rdi
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
.globl syscall3
|
// 6 parameters.
|
||||||
.type syscall3, @function
|
.globl _D5tanya3sys5linux7syscall7syscallFNbNilllllllZl
|
||||||
|
.type _D5tanya3sys5linux7syscall7syscallFNbNilllllllZl, @function
|
||||||
|
|
||||||
syscall3:
|
_D5tanya3sys5linux7syscall7syscallFNbNilllllllZl:
|
||||||
// Store registers.
|
pushq %rbp
|
||||||
movq %rdi, %r8
|
movq %rsp, %rbp
|
||||||
|
|
||||||
movq %rcx, %rax // Syscall number.
|
movq 16(%rbp), %rax
|
||||||
|
|
||||||
// Syscall arguments.
|
mov %rcx, %r10
|
||||||
movq %rdx, %rdi
|
|
||||||
movq %r8, %rdx
|
|
||||||
|
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
// Restore registers.
|
leave
|
||||||
movq %r8, %rdi
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
@ -35,7 +35,7 @@ interface Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Pointer to the new allocated memory.
|
* Returns: Pointer to the new allocated memory.
|
||||||
*/
|
*/
|
||||||
void[] allocate(const size_t size) shared pure nothrow @nogc;
|
void[] allocate(size_t size) shared pure nothrow @nogc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocates a memory block.
|
* Deallocates a memory block.
|
||||||
@ -56,7 +56,7 @@ interface Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Pointer to the allocated memory.
|
* Returns: Pointer to the allocated memory.
|
||||||
*/
|
*/
|
||||||
bool reallocate(ref void[] p, const size_t size) shared pure nothrow @nogc;
|
bool reallocate(ref void[] p, size_t size) shared pure nothrow @nogc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reallocates a memory block in place if possible or returns
|
* Reallocates a memory block in place if possible or returns
|
||||||
@ -70,7 +70,7 @@ interface Allocator
|
|||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise.
|
* Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
bool reallocateInPlace(ref void[] p, const size_t size)
|
bool reallocateInPlace(ref void[] p, size_t size)
|
||||||
shared pure nothrow @nogc;
|
shared pure nothrow @nogc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@ import tanya.memory.allocator;
|
|||||||
final class Mallocator : Allocator
|
final class Mallocator : Allocator
|
||||||
{
|
{
|
||||||
private alias MallocType = extern (C) void* function(size_t)
|
private alias MallocType = extern (C) void* function(size_t)
|
||||||
pure nothrow @system @nogc;
|
@nogc nothrow pure @system;
|
||||||
private alias FreeType = extern (C) void function(void*)
|
private alias FreeType = extern (C) void function(void*)
|
||||||
pure nothrow @system @nogc;
|
@nogc nothrow pure @system;
|
||||||
private alias ReallocType = extern (C) void* function(void*, size_t)
|
private alias ReallocType = extern (C) void* function(void*, size_t)
|
||||||
pure nothrow @system @nogc;
|
@nogc nothrow pure @system;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates $(D_PARAM size) bytes of memory.
|
* Allocates $(D_PARAM size) bytes of memory.
|
||||||
@ -43,7 +43,7 @@ final class Mallocator : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: The pointer to the new allocated memory.
|
* Returns: The pointer to the new allocated memory.
|
||||||
*/
|
*/
|
||||||
void[] allocate(const size_t size) shared pure nothrow @nogc
|
void[] allocate(size_t size) @nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@ -55,7 +55,7 @@ final class Mallocator : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto p = Mallocator.instance.allocate(20);
|
auto p = Mallocator.instance.allocate(20);
|
||||||
assert(p.length == 20);
|
assert(p.length == 20);
|
||||||
@ -73,7 +73,7 @@ final class Mallocator : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the deallocation was successful.
|
* Returns: Whether the deallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool deallocate(void[] p) shared pure nothrow @nogc
|
bool deallocate(void[] p) @nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (p !is null)
|
if (p !is null)
|
||||||
{
|
{
|
||||||
@ -83,7 +83,7 @@ final class Mallocator : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
assert(Mallocator.instance.deallocate(p));
|
assert(Mallocator.instance.deallocate(p));
|
||||||
@ -101,14 +101,14 @@ final class Mallocator : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD false).
|
* Returns: $(D_KEYWORD false).
|
||||||
*/
|
*/
|
||||||
bool reallocateInPlace(ref void[] p, const size_t size)
|
bool reallocateInPlace(ref void[] p, size_t size)
|
||||||
shared pure nothrow @nogc
|
@nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
assert(!Mallocator.instance.reallocateInPlace(p, 8));
|
assert(!Mallocator.instance.reallocateInPlace(p, 8));
|
||||||
@ -123,7 +123,8 @@ final class Mallocator : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the reallocation was successful.
|
* Returns: Whether the reallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool reallocate(ref void[] p, const size_t size) shared pure nothrow @nogc
|
bool reallocate(ref void[] p, size_t size)
|
||||||
|
@nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@ -152,7 +153,7 @@ final class Mallocator : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
|
|
||||||
@ -169,8 +170,8 @@ final class Mallocator : Allocator
|
|||||||
assert(p is null);
|
assert(p is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fails with false.
|
// Fails with false
|
||||||
private @nogc nothrow unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
void[] p = Mallocator.instance.allocate(20);
|
void[] p = Mallocator.instance.allocate(20);
|
||||||
void[] oldP = p;
|
void[] oldP = p;
|
||||||
@ -182,7 +183,7 @@ final class Mallocator : Allocator
|
|||||||
/**
|
/**
|
||||||
* Returns: The alignment offered.
|
* Returns: The alignment offered.
|
||||||
*/
|
*/
|
||||||
@property uint alignment() shared const pure nothrow @safe @nogc
|
@property uint alignment() const @nogc nothrow pure @safe shared
|
||||||
{
|
{
|
||||||
return (void*).alignof;
|
return (void*).alignof;
|
||||||
}
|
}
|
||||||
@ -192,7 +193,7 @@ final class Mallocator : Allocator
|
|||||||
assert(Mallocator.instance.alignment == (void*).alignof);
|
assert(Mallocator.instance.alignment == (void*).alignof);
|
||||||
}
|
}
|
||||||
|
|
||||||
static private shared(Mallocator) instantiate() nothrow @nogc
|
static private shared(Mallocator) instantiate() @nogc nothrow @system
|
||||||
{
|
{
|
||||||
if (instance_ is null)
|
if (instance_ is null)
|
||||||
{
|
{
|
||||||
@ -213,13 +214,13 @@ final class Mallocator : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: The global $(D_PSYMBOL Allocator) instance.
|
* Returns: The global $(D_PSYMBOL Allocator) instance.
|
||||||
*/
|
*/
|
||||||
static @property shared(Mallocator) instance() pure nothrow @nogc
|
static @property shared(Mallocator) instance() @nogc nothrow pure @system
|
||||||
{
|
{
|
||||||
return (cast(GetPureInstance!Mallocator) &instantiate)();
|
return (cast(GetPureInstance!Mallocator) &instantiate)();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
assert(instance is instance);
|
assert(instance is instance);
|
||||||
}
|
}
|
||||||
|
@ -14,45 +14,32 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.memory.mmappool;
|
module tanya.memory.mmappool;
|
||||||
|
|
||||||
import std.algorithm.comparison;
|
|
||||||
import tanya.memory.allocator;
|
|
||||||
import tanya.memory.op;
|
|
||||||
|
|
||||||
version (TanyaNative):
|
version (TanyaNative):
|
||||||
|
|
||||||
import core.sys.posix.sys.mman : MAP_ANON,
|
import mir.linux._asm.unistd;
|
||||||
MAP_FAILED,
|
import tanya.algorithm.comparison;
|
||||||
MAP_PRIVATE,
|
import tanya.memory.allocator;
|
||||||
PROT_READ,
|
import tanya.memory.op;
|
||||||
PROT_WRITE;
|
import tanya.os.error;
|
||||||
import core.sys.posix.unistd;
|
import tanya.sys.linux.syscall;
|
||||||
|
import tanya.sys.posix.mman;
|
||||||
|
|
||||||
extern(C)
|
private void* mapMemory(const size_t length) @nogc nothrow pure @system
|
||||||
private void* mmap(void* addr,
|
|
||||||
size_t len,
|
|
||||||
int prot,
|
|
||||||
int flags,
|
|
||||||
int fd,
|
|
||||||
off_t offset) pure nothrow @system @nogc;
|
|
||||||
|
|
||||||
extern(C)
|
|
||||||
private int munmap(void* addr, size_t len) pure nothrow @system @nogc;
|
|
||||||
|
|
||||||
private void* mapMemory(const size_t len) pure nothrow @system @nogc
|
|
||||||
{
|
{
|
||||||
void* p = mmap(null,
|
auto p = syscall_(0,
|
||||||
len,
|
length,
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANON,
|
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||||
-1,
|
-1,
|
||||||
0);
|
0,
|
||||||
return p is MAP_FAILED ? null : p;
|
NR_mmap);
|
||||||
|
return p == -ErrorCode.noMemory ? null : cast(void*) p;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool unmapMemory(shared void* addr, const size_t len)
|
private bool unmapMemory(shared void* addr, const size_t length)
|
||||||
pure nothrow @system @nogc
|
@nogc nothrow pure @system
|
||||||
{
|
{
|
||||||
return munmap(cast(void*) addr, len) == 0;
|
return syscall_(cast(ptrdiff_t) addr, length, NR_munmap) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -83,7 +70,7 @@ final class MmapPool : Allocator
|
|||||||
{
|
{
|
||||||
version (none)
|
version (none)
|
||||||
{
|
{
|
||||||
pure nothrow @nogc invariant
|
@nogc nothrow pure @system invariant
|
||||||
{
|
{
|
||||||
for (auto r = &head; *r !is null; r = &((*r).next))
|
for (auto r = &head; *r !is null; r = &((*r).next))
|
||||||
{
|
{
|
||||||
@ -107,7 +94,7 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Pointer to the new allocated memory.
|
* Returns: Pointer to the new allocated memory.
|
||||||
*/
|
*/
|
||||||
void[] allocate(const size_t size) shared pure nothrow @nogc
|
void[] allocate(size_t size) @nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@ -128,7 +115,7 @@ final class MmapPool : Allocator
|
|||||||
return data is null ? null : data[0 .. size];
|
return data is null ? null : data[0 .. size];
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto p = MmapPool.instance.allocate(20);
|
auto p = MmapPool.instance.allocate(20);
|
||||||
assert(p);
|
assert(p);
|
||||||
@ -138,15 +125,14 @@ final class MmapPool : Allocator
|
|||||||
assert(p.length == 0);
|
assert(p.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 245: https://issues.caraus.io/issues/245.
|
@nogc nothrow pure @system unittest
|
||||||
@nogc nothrow pure unittest
|
|
||||||
{
|
{
|
||||||
// allocate() check.
|
// allocate() check.
|
||||||
size_t tooMuchMemory = size_t.max
|
size_t tooMuchMemory = size_t.max
|
||||||
- MmapPool.alignment_
|
- MmapPool.alignment_
|
||||||
- BlockEntry.sizeof * 2
|
- BlockEntry.sizeof * 2
|
||||||
- RegionEntry.sizeof
|
- RegionEntry.sizeof
|
||||||
- MmapPool.instance.pageSize;
|
- pageSize;
|
||||||
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
|
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
|
||||||
|
|
||||||
assert(MmapPool.instance.allocate(size_t.max) is null);
|
assert(MmapPool.instance.allocate(size_t.max) is null);
|
||||||
@ -165,7 +151,8 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Data the block points to or $(D_KEYWORD null).
|
* Returns: Data the block points to or $(D_KEYWORD null).
|
||||||
*/
|
*/
|
||||||
private void* findBlock(const ref size_t size) shared pure nothrow @nogc
|
private void* findBlock(const ref size_t size)
|
||||||
|
@nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
Block block1;
|
Block block1;
|
||||||
RegionLoop: for (auto r = head; r !is null; r = r.next)
|
RegionLoop: for (auto r = head; r !is null; r = r.next)
|
||||||
@ -207,7 +194,7 @@ final class MmapPool : Allocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Merge block with the next one.
|
// Merge block with the next one.
|
||||||
private void mergeNext(Block block) shared const pure nothrow @safe @nogc
|
private void mergeNext(Block block) const @nogc nothrow pure @safe shared
|
||||||
{
|
{
|
||||||
block.size = block.size + BlockEntry.sizeof + block.next.size;
|
block.size = block.size + BlockEntry.sizeof + block.next.size;
|
||||||
if (block.next.next !is null)
|
if (block.next.next !is null)
|
||||||
@ -225,7 +212,7 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the deallocation was successful.
|
* Returns: Whether the deallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool deallocate(void[] p) shared pure nothrow @nogc
|
bool deallocate(void[] p) @nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (p.ptr is null)
|
if (p.ptr is null)
|
||||||
{
|
{
|
||||||
@ -271,7 +258,7 @@ final class MmapPool : Allocator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto p = MmapPool.instance.allocate(20);
|
auto p = MmapPool.instance.allocate(20);
|
||||||
|
|
||||||
@ -290,8 +277,8 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise.
|
* Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
bool reallocateInPlace(ref void[] p, const size_t size)
|
bool reallocateInPlace(ref void[] p, size_t size)
|
||||||
shared pure nothrow @nogc
|
@nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (p is null || size == 0)
|
if (p is null || size == 0)
|
||||||
{
|
{
|
||||||
@ -354,7 +341,7 @@ final class MmapPool : Allocator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
assert(!MmapPool.instance.reallocateInPlace(p, 5));
|
assert(!MmapPool.instance.reallocateInPlace(p, 5));
|
||||||
@ -387,7 +374,8 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the reallocation was successful.
|
* Returns: Whether the reallocation was successful.
|
||||||
*/
|
*/
|
||||||
bool reallocate(ref void[] p, const size_t size) shared pure nothrow @nogc
|
bool reallocate(ref void[] p, size_t size)
|
||||||
|
@nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@ -419,7 +407,7 @@ final class MmapPool : Allocator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
void[] p;
|
void[] p;
|
||||||
MmapPool.instance.reallocate(p, 10 * int.sizeof);
|
MmapPool.instance.reallocate(p, 10 * int.sizeof);
|
||||||
@ -447,28 +435,20 @@ final class MmapPool : Allocator
|
|||||||
MmapPool.instance.deallocate(p);
|
MmapPool.instance.deallocate(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static private shared(MmapPool) instantiate() nothrow @nogc
|
static private shared(MmapPool) instantiate() @nogc nothrow @system
|
||||||
{
|
{
|
||||||
if (instance_ is null)
|
if (instance_ is null)
|
||||||
{
|
{
|
||||||
// Get system dependend page size.
|
|
||||||
size_t pageSize = sysconf(_SC_PAGE_SIZE);
|
|
||||||
if (pageSize < 65536)
|
|
||||||
{
|
|
||||||
pageSize = pageSize * 65536 / pageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
const instanceSize = addAlignment(__traits(classInstanceSize,
|
const instanceSize = addAlignment(__traits(classInstanceSize,
|
||||||
MmapPool));
|
MmapPool));
|
||||||
|
|
||||||
Region head; // Will become soon our region list head
|
Region head; // Will become soon our region list head
|
||||||
void* data = initializeRegion(instanceSize, head, pageSize);
|
void* data = initializeRegion(instanceSize, head);
|
||||||
if (data !is null)
|
if (data !is null)
|
||||||
{
|
{
|
||||||
copy(typeid(MmapPool).initializer, data[0 .. instanceSize]);
|
copy(typeid(MmapPool).initializer, data[0 .. instanceSize]);
|
||||||
instance_ = cast(shared MmapPool) data;
|
instance_ = cast(shared MmapPool) data;
|
||||||
instance_.head = head;
|
instance_.head = head;
|
||||||
instance_.pageSize = pageSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return instance_;
|
return instance_;
|
||||||
@ -479,12 +459,12 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Global $(D_PSYMBOL MmapPool) instance.
|
* Returns: Global $(D_PSYMBOL MmapPool) instance.
|
||||||
*/
|
*/
|
||||||
static @property shared(MmapPool) instance() pure nothrow @nogc
|
static @property shared(MmapPool) instance() @nogc nothrow pure @system
|
||||||
{
|
{
|
||||||
return (cast(GetPureInstance!MmapPool) &instantiate)();
|
return (cast(GetPureInstance!MmapPool) &instantiate)();
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
assert(instance is instance);
|
assert(instance is instance);
|
||||||
}
|
}
|
||||||
@ -498,12 +478,10 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: A pointer to the data.
|
* Returns: A pointer to the data.
|
||||||
*/
|
*/
|
||||||
private static void* initializeRegion(const size_t size,
|
private static void* initializeRegion(const size_t size, ref Region head)
|
||||||
ref Region head,
|
@nogc nothrow pure @system
|
||||||
const size_t pageSize)
|
|
||||||
pure nothrow @nogc
|
|
||||||
{
|
{
|
||||||
const regionSize = calculateRegionSize(size, pageSize);
|
const regionSize = calculateRegionSize(size);
|
||||||
if (regionSize < size)
|
if (regionSize < size)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -550,9 +528,10 @@ final class MmapPool : Allocator
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void* initializeRegion(const size_t size) shared pure nothrow @nogc
|
private void* initializeRegion(const size_t size)
|
||||||
|
@nogc nothrow pure shared @system
|
||||||
{
|
{
|
||||||
return initializeRegion(size, this.head, this.pageSize);
|
return initializeRegion(size, this.head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -561,21 +540,19 @@ final class MmapPool : Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Aligned size of $(D_PARAM x).
|
* Returns: Aligned size of $(D_PARAM x).
|
||||||
*/
|
*/
|
||||||
private static size_t addAlignment(const size_t x) pure nothrow @safe @nogc
|
private static size_t addAlignment(const size_t x) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return (x - 1) / alignment_ * alignment_ + alignment_;
|
return (x - 1) / alignment_ * alignment_ + alignment_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Params:
|
* Params:
|
||||||
* x = Required space.
|
* x = Required space.
|
||||||
* pageSize = Page size.
|
|
||||||
*
|
*
|
||||||
* Returns: Minimum region size (a multiple of $(D_PSYMBOL pageSize)).
|
* Returns: Minimum region size (a multiple of $(D_PSYMBOL pageSize)).
|
||||||
*/
|
*/
|
||||||
private static size_t calculateRegionSize(ref const size_t x,
|
private static size_t calculateRegionSize(ref const size_t x)
|
||||||
ref const size_t pageSize)
|
@nogc nothrow pure @safe
|
||||||
pure nothrow @safe @nogc
|
|
||||||
{
|
{
|
||||||
return (x + RegionEntry.sizeof + BlockEntry.sizeof * 2)
|
return (x + RegionEntry.sizeof + BlockEntry.sizeof * 2)
|
||||||
/ pageSize * pageSize + pageSize;
|
/ pageSize * pageSize + pageSize;
|
||||||
@ -584,12 +561,12 @@ final class MmapPool : Allocator
|
|||||||
/*
|
/*
|
||||||
* Returns: Alignment offered.
|
* Returns: Alignment offered.
|
||||||
*/
|
*/
|
||||||
@property uint alignment() shared const pure nothrow @safe @nogc
|
@property uint alignment() const @nogc nothrow pure @safe shared
|
||||||
{
|
{
|
||||||
return alignment_;
|
return alignment_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
assert(MmapPool.instance.alignment == MmapPool.alignment_);
|
assert(MmapPool.instance.alignment == MmapPool.alignment_);
|
||||||
}
|
}
|
||||||
@ -597,7 +574,9 @@ final class MmapPool : Allocator
|
|||||||
private enum uint alignment_ = 8;
|
private enum uint alignment_ = 8;
|
||||||
|
|
||||||
private shared static MmapPool instance_;
|
private shared static MmapPool instance_;
|
||||||
private shared size_t pageSize;
|
|
||||||
|
// Page size.
|
||||||
|
enum size_t pageSize = 65536;
|
||||||
|
|
||||||
private shared struct RegionEntry
|
private shared struct RegionEntry
|
||||||
{
|
{
|
||||||
@ -622,7 +601,7 @@ final class MmapPool : Allocator
|
|||||||
|
|
||||||
// A lot of allocations/deallocations, but it is the minimum caused a
|
// A lot of allocations/deallocations, but it is the minimum caused a
|
||||||
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
|
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
|
||||||
@nogc nothrow pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto a = MmapPool.instance.allocate(16);
|
auto a = MmapPool.instance.allocate(16);
|
||||||
auto d = MmapPool.instance.allocate(16);
|
auto d = MmapPool.instance.allocate(16);
|
||||||
|
47
source/tanya/sys/linux/syscall.d
Normal file
47
source/tanya/sys/linux/syscall.d
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright: Eugene Wissner 2018.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/sys/linux/syscall.d,
|
||||||
|
* tanya/sys/linux/syscall.d)
|
||||||
|
*/
|
||||||
|
module tanya.sys.linux.syscall;
|
||||||
|
|
||||||
|
version (TanyaNative):
|
||||||
|
|
||||||
|
extern ptrdiff_t syscall(ptrdiff_t, ptrdiff_t, ptrdiff_t)
|
||||||
|
@nogc nothrow @system;
|
||||||
|
|
||||||
|
extern ptrdiff_t syscall(ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t) @nogc nothrow @system;
|
||||||
|
|
||||||
|
// Same syscalls as above but pure.
|
||||||
|
private template getOverloadMangling(size_t n)
|
||||||
|
{
|
||||||
|
enum string getOverloadMangling = __traits(getOverloads,
|
||||||
|
tanya.sys.linux.syscall,
|
||||||
|
"syscall")[n].mangleof;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(mangle, getOverloadMangling!0)
|
||||||
|
extern ptrdiff_t syscall_(ptrdiff_t, ptrdiff_t, ptrdiff_t)
|
||||||
|
@nogc nothrow pure @system;
|
||||||
|
|
||||||
|
pragma(mangle, getOverloadMangling!1)
|
||||||
|
extern ptrdiff_t syscall_(ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t,
|
||||||
|
ptrdiff_t) @nogc nothrow pure @system;
|
31
source/tanya/sys/posix/mman.d
Normal file
31
source/tanya/sys/posix/mman.d
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright: Eugene Wissner 2018.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/sys/posix/mman.d,
|
||||||
|
* tanya/sys/posix/mman.d)
|
||||||
|
*/
|
||||||
|
module tanya.sys.posix.mman;
|
||||||
|
|
||||||
|
version (TanyaNative):
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROT_EXEC = 0x4, // Page can be executed.
|
||||||
|
PROT_NONE = 0x0, // Page cannot be accessed.
|
||||||
|
PROT_READ = 0x1, // Page can be read.
|
||||||
|
PROT_WRITE = 0x2, // Page can be written.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAP_FIXED = 0x10, // Interpret addr exactly.
|
||||||
|
MAP_PRIVATE = 0x02, // Changes are private.
|
||||||
|
MAP_SHARED = 0x01, // Share changes.
|
||||||
|
MAP_ANONYMOUS = 0x20, // Don't use a file.
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user