Added 'ansic' os support for minimal (embedded) targets (#13088)
* os:any implementation * os:asny: omit flock/funlock calls in echoBinSafe * Disabled default "unhandled expection" reporting for `--os:any` to reduce code size. Added unhandledExceptionHook instead which can be used to get a notification from Nim and handle it from the application.
This commit is contained in:
parent
d31e32743f
commit
79a326759a
6 changed files with 87 additions and 73 deletions
|
|
@ -210,7 +210,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
|||
# interested in
|
||||
enabled = true
|
||||
|
||||
when not hasThreadSupport:
|
||||
when hasSomeStackTrace and not hasThreadSupport:
|
||||
var
|
||||
tempFrames: array[0..127, PFrame] # should not be alloc'd on stack
|
||||
|
||||
|
|
@ -261,52 +261,53 @@ proc `$`(s: seq[StackTraceEntry]): string =
|
|||
elif s[i].line == reraisedFromEnd: result.add "]]\n"
|
||||
else: addFrameEntry(result, s[i])
|
||||
|
||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
when hasThreadSupport:
|
||||
var
|
||||
tempFrames: array[0..127, PFrame] # but better than a threadvar
|
||||
const
|
||||
firstCalls = 32
|
||||
var
|
||||
it = f
|
||||
i = 0
|
||||
total = 0
|
||||
# setup long head:
|
||||
while it != nil and i <= high(tempFrames)-firstCalls:
|
||||
tempFrames[i] = it
|
||||
inc(i)
|
||||
inc(total)
|
||||
it = it.prev
|
||||
# go up the stack to count 'total':
|
||||
var b = it
|
||||
while it != nil:
|
||||
inc(total)
|
||||
it = it.prev
|
||||
var skipped = 0
|
||||
if total > len(tempFrames):
|
||||
# skip N
|
||||
skipped = total-i-firstCalls+1
|
||||
for j in 1..skipped:
|
||||
if b != nil: b = b.prev
|
||||
# create '...' entry:
|
||||
tempFrames[i] = nil
|
||||
inc(i)
|
||||
# setup short tail:
|
||||
while b != nil and i <= high(tempFrames):
|
||||
tempFrames[i] = b
|
||||
inc(i)
|
||||
b = b.prev
|
||||
for j in countdown(i-1, 0):
|
||||
if tempFrames[j] == nil:
|
||||
add(s, "(")
|
||||
add(s, $skipped)
|
||||
add(s, " calls omitted) ...\n")
|
||||
else:
|
||||
addFrameEntry(s, tempFrames[j])
|
||||
|
||||
proc stackTraceAvailable*(): bool
|
||||
|
||||
when hasSomeStackTrace:
|
||||
|
||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
when hasThreadSupport:
|
||||
var
|
||||
tempFrames: array[0..127, PFrame] # but better than a threadvar
|
||||
const
|
||||
firstCalls = 32
|
||||
var
|
||||
it = f
|
||||
i = 0
|
||||
total = 0
|
||||
# setup long head:
|
||||
while it != nil and i <= high(tempFrames)-firstCalls:
|
||||
tempFrames[i] = it
|
||||
inc(i)
|
||||
inc(total)
|
||||
it = it.prev
|
||||
# go up the stack to count 'total':
|
||||
var b = it
|
||||
while it != nil:
|
||||
inc(total)
|
||||
it = it.prev
|
||||
var skipped = 0
|
||||
if total > len(tempFrames):
|
||||
# skip N
|
||||
skipped = total-i-firstCalls+1
|
||||
for j in 1..skipped:
|
||||
if b != nil: b = b.prev
|
||||
# create '...' entry:
|
||||
tempFrames[i] = nil
|
||||
inc(i)
|
||||
# setup short tail:
|
||||
while b != nil and i <= high(tempFrames):
|
||||
tempFrames[i] = b
|
||||
inc(i)
|
||||
b = b.prev
|
||||
for j in countdown(i-1, 0):
|
||||
if tempFrames[j] == nil:
|
||||
add(s, "(")
|
||||
add(s, $skipped)
|
||||
add(s, " calls omitted) ...\n")
|
||||
else:
|
||||
addFrameEntry(s, tempFrames[j])
|
||||
|
||||
proc stackTraceAvailable*(): bool
|
||||
|
||||
proc rawWriteStackTrace(s: var string) =
|
||||
when defined(nimStackTraceOverride):
|
||||
add(s, "Traceback (most recent call last, using override)\n")
|
||||
|
|
@ -351,7 +352,7 @@ var onUnhandledException*: (proc (errorMsg: string) {.
|
|||
## The default is to write a stacktrace to ``stderr`` and then call ``quit(1)``.
|
||||
## Unstable API.
|
||||
|
||||
proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
|
||||
proc reportUnhandledErrorAux(e: ref Exception) {.nodestroy.} =
|
||||
when hasSomeStackTrace:
|
||||
var buf = newStringOfCap(2000)
|
||||
if e.trace.len == 0:
|
||||
|
|
@ -400,6 +401,14 @@ proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
|
|||
else:
|
||||
showErrorMessage(tbuf())
|
||||
|
||||
proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
|
||||
if unhandledExceptionHook != nil:
|
||||
unhandledExceptionHook(e)
|
||||
when hostOS != "any":
|
||||
reportUnhandledErrorAux(e)
|
||||
else:
|
||||
discard()
|
||||
|
||||
proc nimLeaveFinally() {.compilerRtl.} =
|
||||
when defined(cpp) and not defined(noCppExceptions):
|
||||
{.emit: "throw;".}
|
||||
|
|
@ -425,14 +434,6 @@ when gotoBasedExceptions:
|
|||
currException = nil
|
||||
quit(1)
|
||||
|
||||
addQuitProc(proc () {.noconv.} =
|
||||
if currException != nil:
|
||||
reportUnhandledError(currException)
|
||||
# emulate: ``programResult = 1`` via abort() and a nop signal handler.
|
||||
c_signal(SIGABRT, (proc (sign: cint) {.noconv, benign.} = discard))
|
||||
c_abort()
|
||||
)
|
||||
|
||||
proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
|
||||
if localRaiseHook != nil:
|
||||
if not localRaiseHook(e): return
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ when declared(stdout):
|
|||
android_log_print(ANDROID_LOG_VERBOSE, "nim", s)
|
||||
else:
|
||||
# flockfile deadlocks some versions of Android 5.x.x
|
||||
when not defined(windows) and not defined(android) and not defined(nintendoswitch):
|
||||
when not defined(windows) and not defined(android) and not defined(nintendoswitch) and hostOS != "any":
|
||||
proc flockfile(f: File) {.importc, nodecl.}
|
||||
proc funlockfile(f: File) {.importc, nodecl.}
|
||||
flockfile(stdout)
|
||||
|
|
@ -629,7 +629,7 @@ when declared(stdout):
|
|||
const linefeed = "\n"
|
||||
discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout)
|
||||
discard c_fflush(stdout)
|
||||
when not defined(windows) and not defined(android) and not defined(nintendoswitch):
|
||||
when not defined(windows) and not defined(android) and not defined(nintendoswitch) and hostOS != "any":
|
||||
funlockfile(stdout)
|
||||
when defined(windows) and compileOption("threads"):
|
||||
releaseSys echoLock
|
||||
|
|
|
|||
|
|
@ -354,11 +354,11 @@ elif defined(gogc):
|
|||
proc deallocOsPages(r: var MemRegion) {.inline.} = discard
|
||||
proc deallocOsPages() {.inline.} = discard
|
||||
|
||||
elif defined(nogc) and defined(useMalloc):
|
||||
elif (defined(nogc) or defined(gcDestructors)) and defined(useMalloc):
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc alloc(size: Natural): pointer =
|
||||
var x = c_malloc(size + sizeof(size))
|
||||
var x = c_malloc (size + sizeof(size)).csize_t
|
||||
if x == nil: raiseOutOfMem()
|
||||
|
||||
cast[ptr int](x)[] = size
|
||||
|
|
@ -371,7 +371,7 @@ elif defined(nogc) and defined(useMalloc):
|
|||
var x = cast[pointer](cast[int](p) - sizeof(newsize))
|
||||
let oldsize = cast[ptr int](x)[]
|
||||
|
||||
x = c_realloc(x, newsize + sizeof(newsize))
|
||||
x = c_realloc(x, (newsize + sizeof(newsize)).csize_t)
|
||||
|
||||
if x == nil: raiseOutOfMem()
|
||||
|
||||
|
|
@ -384,13 +384,13 @@ elif defined(nogc) and defined(useMalloc):
|
|||
proc dealloc(p: pointer) = c_free(cast[pointer](cast[int](p) - sizeof(int)))
|
||||
|
||||
proc allocShared(size: Natural): pointer =
|
||||
result = c_malloc(size)
|
||||
result = c_malloc(size.csize_t)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc allocShared0(size: Natural): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc reallocShared(p: pointer, newsize: Natural): pointer =
|
||||
result = c_realloc(p, newsize)
|
||||
result = c_realloc(p, newsize.csize_t)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc deallocShared(p: pointer) = c_free(p)
|
||||
|
||||
|
|
@ -400,7 +400,7 @@ elif defined(nogc) and defined(useMalloc):
|
|||
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
#proc GC_getStatistics(): string = return ""
|
||||
|
||||
proc getOccupiedMem(): int = discard
|
||||
proc getFreeMem(): int = discard
|
||||
|
|
@ -410,13 +410,6 @@ elif defined(nogc) and defined(useMalloc):
|
|||
|
||||
proc initGC() = discard
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||
result = alloc0(size)
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||
result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
|
||||
cast[PGenericSeq](result).len = len
|
||||
cast[PGenericSeq](result).reserved = len
|
||||
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer =
|
||||
result = alloc(size)
|
||||
|
||||
|
|
|
|||
|
|
@ -295,5 +295,16 @@ elif hostOS == "standalone" or defined(StandaloneHeapSize):
|
|||
proc osDeallocPages(p: pointer, size: int) {.inline.} =
|
||||
if bumpPointer-size == cast[int](p):
|
||||
dec bumpPointer, size
|
||||
|
||||
elif hostOS == "any":
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
result = c_malloc(size.csize_t)
|
||||
|
||||
proc osTryAllocPages(size: int): pointer {.inline.} =
|
||||
result = c_malloc(size.csize_t)
|
||||
|
||||
proc osDeallocPages(p: pointer, size: int) {.inline.} =
|
||||
c_free(p)
|
||||
|
||||
else:
|
||||
{.error: "Port memory manager to your platform".}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue