added nimAllocPagesViaMalloc switch (#18490)
* added switch * alloc.nim needs page aligned memory blocks
This commit is contained in:
parent
8c6dd2b9a9
commit
af3d2d8ad9
5 changed files with 46 additions and 7 deletions
|
|
@ -391,6 +391,9 @@
|
||||||
- The `gc:orc` algorithm was refined so that custom container types can participate in the
|
- The `gc:orc` algorithm was refined so that custom container types can participate in the
|
||||||
cycle collection process.
|
cycle collection process.
|
||||||
|
|
||||||
|
- On embedded devices `malloc` can now be used instead of `mmap` via `-d:nimAllocPagesViaMalloc`.
|
||||||
|
This is only supported for `--gc:orc` or `--gc:arc`.
|
||||||
|
|
||||||
|
|
||||||
## Compiler changes
|
## Compiler changes
|
||||||
|
|
||||||
|
|
|
||||||
14
doc/nimc.rst
14
doc/nimc.rst
|
|
@ -176,7 +176,7 @@ directories (in this order; later files overwrite previous settings):
|
||||||
``%APPDATA%/nim/nim.cfg`` (Windows).
|
``%APPDATA%/nim/nim.cfg`` (Windows).
|
||||||
This file can be skipped with the `--skipUserCfg`:option: command line
|
This file can be skipped with the `--skipUserCfg`:option: command line
|
||||||
option.
|
option.
|
||||||
3) ``$parentDir/nim.cfg`` where ``$parentDir`` stands for any parent
|
3) ``$parentDir/nim.cfg`` where ``$parentDir`` stands for any parent
|
||||||
directory of the project file's path.
|
directory of the project file's path.
|
||||||
These files can be skipped with the `--skipParentCfg`:option:
|
These files can be skipped with the `--skipParentCfg`:option:
|
||||||
command-line option.
|
command-line option.
|
||||||
|
|
@ -634,6 +634,18 @@ optimization in the compiler and linker.
|
||||||
Check the `Cross-compilation`_ section for instructions on how to compile the
|
Check the `Cross-compilation`_ section for instructions on how to compile the
|
||||||
program for your target.
|
program for your target.
|
||||||
|
|
||||||
|
|
||||||
|
nimAllocPagesViaMalloc
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Nim's default allocator is based on TLSF, this algorithm was designed for embedded
|
||||||
|
devices. This allocator gets blocks/pages of memory via a currently undocumented
|
||||||
|
`osalloc` API which usually uses POSIX's `mmap` call. On many environments `mmap`
|
||||||
|
is not available but C's `malloc` is. You can use the `nimAllocPagesViaMalloc`
|
||||||
|
define to use `malloc` instead of `mmap`. `nimAllocPagesViaMalloc` is currently
|
||||||
|
only supported with `--gc:arc` or `--gc:orc`. (Since version 1.6)
|
||||||
|
|
||||||
|
|
||||||
Nim for realtime systems
|
Nim for realtime systems
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -749,8 +749,9 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
|
||||||
inc(a.allocCounter)
|
inc(a.allocCounter)
|
||||||
sysAssert(allocInv(a), "rawAlloc: begin")
|
sysAssert(allocInv(a), "rawAlloc: begin")
|
||||||
sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
|
sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
|
||||||
sysAssert(requestedSize >= sizeof(FreeCell), "rawAlloc: requested size too small")
|
|
||||||
var size = roundup(requestedSize, MemAlign)
|
var size = roundup(requestedSize, MemAlign)
|
||||||
|
sysAssert(size >= sizeof(FreeCell), "rawAlloc: requested size too small")
|
||||||
|
|
||||||
sysAssert(size >= requestedSize, "insufficient allocated size!")
|
sysAssert(size >= requestedSize, "insufficient allocated size!")
|
||||||
#c_fprintf(stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
|
#c_fprintf(stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
|
||||||
if size <= SmallChunkSize-smallChunkOverhead():
|
if size <= SmallChunkSize-smallChunkOverhead():
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,30 @@ const doNotUnmap = not (defined(amd64) or defined(i386)) or
|
||||||
defined(windows) or defined(nimAllocNoUnmap)
|
defined(windows) or defined(nimAllocNoUnmap)
|
||||||
|
|
||||||
|
|
||||||
when defined(emscripten) and not defined(StandaloneHeapSize):
|
when defined(nimAllocPagesViaMalloc):
|
||||||
|
when not defined(gcArc) and not defined(gcOrc):
|
||||||
|
{.error: "-d:nimAllocPagesViaMalloc is only supported with --gc:arc or --gc:orc".}
|
||||||
|
|
||||||
|
proc osTryAllocPages(size: int): pointer {.inline.} =
|
||||||
|
let base = c_malloc(csize_t size + PageSize - 1 + sizeof(uint32))
|
||||||
|
if base == nil: raiseOutOfMem()
|
||||||
|
# memory layout: padding + offset (4 bytes) + user_data
|
||||||
|
# in order to deallocate: read offset at user_data - 4 bytes,
|
||||||
|
# then deallocate user_data - offset
|
||||||
|
let offset = PageSize - (cast[int](base) and (PageSize - 1))
|
||||||
|
cast[ptr uint32](base +! (offset - sizeof(uint32)))[] = uint32(offset)
|
||||||
|
result = base +! offset
|
||||||
|
|
||||||
|
proc osAllocPages(size: int): pointer {.inline.} =
|
||||||
|
result = osTryAllocPages(size)
|
||||||
|
if result == nil: raiseOutOfMem()
|
||||||
|
|
||||||
|
proc osDeallocPages(p: pointer, size: int) {.inline.} =
|
||||||
|
# read offset at p - 4 bytes, then deallocate (p - offset) pointer
|
||||||
|
let offset = cast[ptr uint32](p -! sizeof(uint32))[]
|
||||||
|
c_free(p -! offset)
|
||||||
|
|
||||||
|
elif defined(emscripten) and not defined(StandaloneHeapSize):
|
||||||
const
|
const
|
||||||
PROT_READ = 1 # page can be read
|
PROT_READ = 1 # page can be read
|
||||||
PROT_WRITE = 2 # page can be written
|
PROT_WRITE = 2 # page can be written
|
||||||
|
|
@ -197,11 +220,11 @@ elif defined(posix) and not defined(StandaloneHeapSize):
|
||||||
PROT_WRITE = 2 # page can be written
|
PROT_WRITE = 2 # page can be written
|
||||||
|
|
||||||
when defined(netbsd) or defined(openbsd):
|
when defined(netbsd) or defined(openbsd):
|
||||||
# OpenBSD security for setjmp/longjmp coroutines
|
# OpenBSD security for setjmp/longjmp coroutines
|
||||||
var MAP_STACK {.importc: "MAP_STACK", header: "<sys/mman.h>".}: cint
|
var MAP_STACK {.importc: "MAP_STACK", header: "<sys/mman.h>".}: cint
|
||||||
else:
|
else:
|
||||||
const MAP_STACK = 0 # avoid sideeffects
|
const MAP_STACK = 0 # avoid sideeffects
|
||||||
|
|
||||||
when defined(macosx) or defined(freebsd):
|
when defined(macosx) or defined(freebsd):
|
||||||
const MAP_ANONYMOUS = 0x1000
|
const MAP_ANONYMOUS = 0x1000
|
||||||
const MAP_PRIVATE = 0x02 # Changes are private
|
const MAP_PRIVATE = 0x02 # Changes are private
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ closed
|
||||||
destroying variable: 20
|
destroying variable: 20
|
||||||
destroying variable: 10
|
destroying variable: 10
|
||||||
'''
|
'''
|
||||||
cmd: "nim c --gc:arc --deepcopy:on $file"
|
cmd: "nim c --gc:arc --deepcopy:on -d:nimAllocPagesViaMalloc $file"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc takeSink(x: sink string): bool = true
|
proc takeSink(x: sink string): bool = true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue