fixes merge conflict

This commit is contained in:
Andreas Rumpf 2018-06-11 01:25:48 +02:00
commit 61d9292095
24 changed files with 360 additions and 105 deletions

View file

@ -8,10 +8,15 @@
#
# Low level dataspace allocator for Genode.
# For interacting with dataspaces outside of the
# standard library see the Genode Nimble package.
when not defined(genode):
{.error: "Genode only module".}
when not declared(GenodeEnv):
include genode/env
type DataspaceCapability {.
importcpp: "Genode::Dataspace_capability", pure.} = object
@ -31,35 +36,35 @@ type
const SlabBackendSize = 4096
proc ramAvail(): int {.
importcpp: "genodeEnv->pd().avail_ram().value".}
proc ramAvail(env: GenodeEnv): int {.
importcpp: "#->pd().avail_ram().value".}
## Return number of bytes available for allocation.
proc capsAvail(): int {.
importcpp: "genodeEnv->pd().avail_caps().value".}
proc capsAvail(env: GenodeEnv): int {.
importcpp: "#->pd().avail_caps().value".}
## Return the number of available capabilities.
## Each dataspace allocation consumes a capability.
proc allocDataspace(size: int): DataspaceCapability {.
importcpp: "genodeEnv->pd().alloc(@)".}
proc allocDataspace(env: GenodeEnv; size: int): DataspaceCapability {.
importcpp: "#->pd().alloc(@)".}
## Allocate a dataspace and its capability.
proc attachDataspace(ds: DataspaceCapability): pointer {.
importcpp: "genodeEnv->rm().attach(@)".}
proc attachDataspace(env: GenodeEnv; ds: DataspaceCapability): pointer {.
importcpp: "#->rm().attach(@)".}
## Attach a dataspace into the component address-space.
proc detachAddress(p: pointer) {.
importcpp: "genodeEnv->rm().detach(@)".}
proc detachAddress(env: GenodeEnv; p: pointer) {.
importcpp: "#->rm().detach(@)".}
## Detach a dataspace from the component address-space.
proc freeDataspace(ds: DataspaceCapability) {.
importcpp: "genodeEnv->pd().free(@)".}
proc freeDataspace(env: GenodeEnv; ds: DataspaceCapability) {.
importcpp: "#->pd().free(@)".}
## Free a dataspace.
proc newMapSlab(): ptr MapSlab =
let
ds = allocDataspace SlabBackendSize
p = attachDataspace ds
ds = runtimeEnv.allocDataspace SlabBackendSize
p = runtimeEnv.attachDataspace ds
result = cast[ptr MapSlab](p)
result.meta.ds = ds
@ -89,13 +94,13 @@ proc osAllocPages(size: int): pointer =
# tack a new slab on the tail
slab = slab.meta.next
# move to next slab in linked list
map.ds = allocDataspace size
map.ds = runtimeEnv.allocDataspace size
map.size = size
map.attachment = attachDataspace map.ds
map.attachment = runtimeEnv.attachDataspace map.ds
result = map.attachment
proc osTryAllocPages(size: int): pointer =
if ramAvail() >= size and capsAvail() > 1:
if runtimeEnv.ramAvail() >= size and runtimeEnv.capsAvail() > 4:
result = osAllocPages size
proc osDeallocPages(p: pointer; size: int) =
@ -107,8 +112,8 @@ proc osDeallocPages(p: pointer; size: int) =
if m.size != size:
echo "cannot partially detach dataspace"
quit -1
detachAddress m.attachment
freeDataspace m.ds
runtimeEnv.detachAddress m.attachment
runtimeEnv.freeDataspace m.ds
m[] = Map()
return
slab = slab.meta.next

29
lib/genode/env.nim Normal file
View file

@ -0,0 +1,29 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2018 Emery Hemingway
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
#
# This file contains the minimum required definitions
# for interacting with the initial Genode environment.
# It is reserved for use only within the standard
# library. See ``componentConstructHook`` in the system
# module for accessing the Genode environment after the
# standard library has finished initializating.
#
when not defined(genode):
{.error: "Genode only include".}
type
GenodeEnvObj {.importcpp: "Genode::Env", header: "<base/env.h>", pure.} = object
GenodeEnvPtr = ptr GenodeEnvObj
const runtimeEnvSym = "nim_runtime_env"
when not defined(nimscript):
var runtimeEnv {.importcpp: runtimeEnvSym.}: GenodeEnvPtr

View file

@ -13,6 +13,7 @@
#define _GENODE_CPP__THREAD_H_
#include <base/thread.h>
#include <base/env.h>
#include <util/reconstructible.h>
namespace Nim { struct SysThread; }

View file

@ -502,11 +502,6 @@ typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == siz
# include <sys/types.h>
#endif
#if defined(__GENODE__)
#include <libc/component.h>
extern Libc::Env *genodeEnv;
#endif
/* Compile with -d:checkAbi and a sufficiently C11:ish compiler to enable */
#define NIM_CHECK_SIZE(typ, sz) \
_Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size")

View file

@ -129,6 +129,20 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
proc sendStatus(client: AsyncSocket, status: string): Future[void] =
client.send("HTTP/1.1 " & status & "\c\L\c\L")
proc parseUppercaseMethod(name: string): HttpMethod =
result =
case name
of "GET": HttpGet
of "POST": HttpPost
of "HEAD": HttpHead
of "PUT": HttpPut
of "DELETE": HttpDelete
of "PATCH": HttpPatch
of "OPTIONS": HttpOptions
of "CONNECT": HttpConnect
of "TRACE": HttpTrace
else: raise newException(ValueError, "Invalid HTTP method " & name)
proc processRequest(server: AsyncHttpServer, req: FutureVar[Request],
client: AsyncSocket,
address: string, lineFut: FutureVar[string],
@ -172,8 +186,7 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request],
case i
of 0:
try:
# TODO: this is likely slow.
request.reqMethod = parseEnum[HttpMethod]("http" & linePart)
request.reqMethod = parseUppercaseMethod(linePart)
except ValueError:
asyncCheck request.respondError(Http400)
return

View file

@ -165,16 +165,18 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool =
proc inc*(c: var CritBitTree[int]; key: string, val: int = 1) =
## increments `c[key]` by `val`.
let oldCount = c.count
var n = rawInsert(c, key)
if c.count >= oldCount or oldCount == 0:
# not a new key:
inc n.val, val
inc n.val, val
proc incl*(c: var CritBitTree[void], key: string) =
## includes `key` in `c`.
discard rawInsert(c, key)
proc incl*[T](c: var CritBitTree[T], key: string, val: T) =
## inserts `key` with value `val` into `c`.
var n = rawInsert(c, key)
n.val = val
proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) =
## puts a (key, value)-pair into `t`.
var n = rawInsert(c, key)
@ -375,3 +377,18 @@ when isMainModule:
c.inc("a", 1)
assert c["a"] == 1
var cf = CritBitTree[float]()
cf.incl("a", 1.0)
assert cf["a"] == 1.0
cf.incl("b", 2.0)
assert cf["b"] == 2.0
cf.incl("c", 3.0)
assert cf["c"] == 3.0
assert cf.len == 3
cf.excl("c")
assert cf.len == 2

View file

@ -38,8 +38,10 @@ when defined(macosx) or defined(bsd):
importc: "sysctl", nodecl.}
when defined(genode):
proc affinitySpaceTotal(): cuint {.
importcpp: "genodeEnv->cpu().affinity_space().total()".}
include genode/env
proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
importcpp: "@->cpu().affinity_space().total()".}
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## returns the numer of the processors/cores the machine has.
@ -83,7 +85,7 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
result = sysconf(SC_NPROC_ONLN)
elif defined(genode):
result = affinitySpaceTotal().int
result = runtimeEnv.affinitySpaceTotal().int
else:
result = sysconf(SC_NPROCESSORS_ONLN)
if result <= 0: result = 0

View file

@ -447,7 +447,7 @@ proc fromSockAddr*(sa: Sockaddr_storage | SockAddr | Sockaddr_in | Sockaddr_in6,
sl: Socklen, address: var IpAddress, port: var Port) {.inline.} =
## Converts `SockAddr` and `Socklen` to `IpAddress` and `Port`. Raises
## `ObjectConversionError` in case of invalid `sa` and `sl` arguments.
fromSockAddrAux(unsafeAddr sa, sl, address, port)
fromSockAddrAux(cast[ptr Sockaddr_storage](unsafeAddr sa), sl, address, port)
when defineSsl:
CRYPTO_malloc_init()

View file

@ -1440,7 +1440,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
elif defined(solaris):
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
elif defined(genode):
raiseOSError("POSIX command line not supported")
raiseOSError(OSErrorCode(-1), "POSIX command line not supported")
elif defined(freebsd) or defined(dragonfly):
result = getApplFreebsd()
# little heuristic that may work on other POSIX-like systems:

View file

@ -150,23 +150,52 @@ proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
## characters and there is at least one character in `s`.
isImpl isSpaceAscii
proc isLowerAscii*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nsuIsLowerAsciiStr".} =
## Checks whether or not `s` contains all lower case characters.
##
## This checks ASCII characters only.
## Returns true if all characters in `s` are lower case
## and there is at least one character in `s`.
isImpl isLowerAscii
template isCaseImpl(s, charProc, skipNonAlpha) =
var hasAtleastOneAlphaChar = false
if s.len == 0: return false
for c in s:
if skipNonAlpha:
var charIsAlpha = c.isAlphaAscii()
if not hasAtleastOneAlphaChar:
hasAtleastOneAlphaChar = charIsAlpha
if charIsAlpha and (not charProc(c)):
return false
else:
if not charProc(c):
return false
return if skipNonAlpha: hasAtleastOneAlphaChar else: true
proc isUpperAscii*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nsuIsUpperAsciiStr".} =
## Checks whether or not `s` contains all upper case characters.
proc isLowerAscii*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is lower case.
##
## This checks ASCII characters only.
## Returns true if all characters in `s` are upper case
## and there is at least one character in `s`.
isImpl isUpperAscii
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## characters in ``s`` are lower case. Returns false if none of the
## characters in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all characters
## in ``s`` are alphabetical and lower case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
isCaseImpl(s, isLowerAscii, skipNonAlpha)
proc isUpperAscii*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is upper case.
##
## This checks ASCII characters only.
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## characters in ``s`` are upper case. Returns false if none of the
## characters in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all characters
## in ``s`` are alphabetical and upper case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
isCaseImpl(s, isUpperAscii, skipNonAlpha)
proc toLowerAscii*(c: char): char {.noSideEffect, procvar,
rtl, extern: "nsuToLowerAsciiChar".} =
@ -2516,19 +2545,34 @@ when isMainModule:
doAssert(not isLowerAscii('A'))
doAssert(not isLowerAscii('5'))
doAssert(not isLowerAscii('&'))
doAssert(not isLowerAscii(' '))
doAssert isLowerAscii("abcd")
doAssert(not isLowerAscii("abCD"))
doAssert(not isLowerAscii("33aa"))
doAssert isLowerAscii("abcd", false)
doAssert(not isLowerAscii("33aa", false))
doAssert(not isLowerAscii("a b", false))
doAssert(not isLowerAscii("abCD", true))
doAssert isLowerAscii("33aa", true)
doAssert isLowerAscii("a b", true)
doAssert isLowerAscii("1, 2, 3 go!", true)
doAssert(not isLowerAscii(" ", true))
doAssert(not isLowerAscii("(*&#@(^#$ ", true)) # None of the string chars are alphabets
doAssert isUpperAscii('A')
doAssert(not isUpperAscii('b'))
doAssert(not isUpperAscii('5'))
doAssert(not isUpperAscii('%'))
doAssert isUpperAscii("ABC")
doAssert(not isUpperAscii("AAcc"))
doAssert(not isUpperAscii("A#$"))
doAssert isUpperAscii("ABC", false)
doAssert(not isUpperAscii("A#$", false))
doAssert(not isUpperAscii("A B", false))
doAssert(not isUpperAscii("AAcc", true))
doAssert isUpperAscii("A#$", true)
doAssert isUpperAscii("A B", true)
doAssert isUpperAscii("1, 2, 3 GO!", true)
doAssert(not isUpperAscii(" ", true))
doAssert(not isUpperAscii("(*&#@(^#$ ", true)) # None of the string chars are alphabets
doAssert rsplit("foo bar", seps=Whitespace) == @["foo", "bar"]
doAssert rsplit(" foo bar", seps=Whitespace, maxsplit=1) == @[" foo", "bar"]
@ -2601,4 +2645,3 @@ bar
nonStaticTests()
staticTests()
static: staticTests()

View file

@ -1392,7 +1392,7 @@ proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
(c >= 0xfe20 and c <= 0xfe2f))
template runeCheck(s, runeProc) =
## Common code for rune.isLower, rune.isUpper, etc
## Common code for isAlpha and isSpace.
result = if len(s) == 0: false else: true
var
@ -1403,16 +1403,6 @@ template runeCheck(s, runeProc) =
fastRuneAt(s, i, rune, doInc=true)
result = runeProc(rune) and result
proc isUpper*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nuc$1Str".} =
## Returns true iff `s` contains all upper case unicode characters.
runeCheck(s, isUpper)
proc isLower*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nuc$1Str".} =
## Returns true iff `s` contains all lower case unicode characters.
runeCheck(s, isLower)
proc isAlpha*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nuc$1Str".} =
## Returns true iff `s` contains all alphabetic unicode characters.
@ -1423,6 +1413,56 @@ proc isSpace*(s: string): bool {.noSideEffect, procvar,
## Returns true iff `s` contains all whitespace unicode characters.
runeCheck(s, isWhiteSpace)
template runeCaseCheck(s, runeProc, skipNonAlpha) =
## Common code for rune.isLower and rune.isUpper.
if len(s) == 0: return false
var
i = 0
rune: Rune
hasAtleastOneAlphaRune = false
while i < len(s):
fastRuneAt(s, i, rune, doInc=true)
if skipNonAlpha:
var runeIsAlpha = isAlpha(rune)
if not hasAtleastOneAlphaRune:
hasAtleastOneAlphaRune = runeIsAlpha
if runeIsAlpha and (not runeProc(rune)):
return false
else:
if not runeProc(rune):
return false
return if skipNonAlpha: hasAtleastOneAlphaRune else: true
proc isLower*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is lower case.
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## runes in ``s`` are lower case. Returns false if none of the
## runes in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all runes in
## ``s`` are alphabetical and lower case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
runeCaseCheck(s, isLower, skipNonAlpha)
proc isUpper*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is upper case.
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## runes in ``s`` are upper case. Returns false if none of the
## runes in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all runes in
## ``s`` are alphabetical and upper case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
runeCaseCheck(s, isUpper, skipNonAlpha)
template convertRune(s, runeProc) =
## Convert runes in `s` using `runeProc` as the converter.
result = newString(len(s))
@ -1755,25 +1795,39 @@ when isMainModule:
doAssert(not isSpace(""))
doAssert(not isSpace("ΑΓc \td"))
doAssert isLower("a")
doAssert isLower("γ")
doAssert(not isLower("Γ"))
doAssert(not isLower("4"))
doAssert(not isLower(""))
doAssert(not isLower(' '.Rune))
doAssert isLower("abcdγ")
doAssert(not isLower("abCDΓ"))
doAssert(not isLower("33aaΓ"))
doAssert isLower("a", false)
doAssert isLower("γ", true)
doAssert(not isLower("Γ", false))
doAssert(not isLower("4", true))
doAssert(not isLower("", false))
doAssert isLower("abcdγ", false)
doAssert(not isLower("33aaΓ", false))
doAssert(not isLower("a b", false))
doAssert isUpper("Γ")
doAssert(not isUpper("b"))
doAssert(not isUpper("α"))
doAssert(not isUpper("✓"))
doAssert(not isUpper(""))
doAssert(not isLower("abCDΓ", true))
doAssert isLower("a b", true)
doAssert isLower("1, 2, 3 go!", true)
doAssert(not isLower(" ", true))
doAssert(not isLower("(*&#@(^#$✓ ", true)) # None of the string runes are alphabets
doAssert isUpper("ΑΒΓ")
doAssert(not isUpper("AAccβ"))
doAssert(not isUpper("A#$β"))
doAssert(not isUpper(' '.Rune))
doAssert isUpper("Γ", false)
doAssert(not isUpper("α", false))
doAssert(not isUpper("", false))
doAssert isUpper("ΑΒΓ", false)
doAssert(not isUpper("A#$β", false))
doAssert(not isUpper("A B", false))
doAssert(not isUpper("b", true))
doAssert(not isUpper("✓", true))
doAssert(not isUpper("AAccβ", true))
doAssert isUpper("A B", true)
doAssert isUpper("1, 2, 3 GO!", true)
doAssert(not isUpper(" ", true))
doAssert(not isUpper("(*&#@(^#$✓ ", true)) # None of the string runes are alphabets
doAssert toUpper("Γ") == "Γ"
doAssert toUpper("b") == "B"

View file

@ -1498,11 +1498,21 @@ when defined(nimdoc):
## macro, use the `error <manual.html#error-pragma>`_ or `fatal
## <manual.html#fatal-pragma>`_ pragmas.
elif defined(genode):
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn,
importcpp: "genodeEnv->parent().exit(@); Genode::sleep_forever()",
header: "<base/sleep.h>".}
include genode/env
var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr
type GenodeEnv* = GenodeEnvPtr
## Opaque type representing Genode environment.
proc quit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn,
importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "<base/sleep.h>".}
proc quit*(errorcode: int = QuitSuccess) =
systemEnv.quit(errorCode)
elif defined(nodejs):
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit",
@ -4215,3 +4225,22 @@ when not defined(js):
type
ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro
## as a `for-loop macro`:idx:
when defined(genode):
var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.}
## Hook into the Genode component bootstrap process.
## This hook is called after all globals are initialized.
## When this hook is set the component will not automatically exit,
## call ``quit`` explicitly to do so. This is the only available method
## of accessing the initial Genode environment.
proc nim_component_construct(env: GenodeEnv) {.exportc.} =
## Procedure called during ``Component::construct`` by the loader.
if componentConstructHook.isNil:
env.quit(programResult)
# No native Genode application initialization,
# exit as would POSIX.
else:
componentConstructHook(env)
# Perform application initialization
# and return to thread entrypoint.

View file

@ -78,7 +78,7 @@ when defined(emscripten):
munmap(mmapDescr.realPointer, mmapDescr.realSize)
elif defined(genode):
include genodealloc # osAllocPages, osTryAllocPages, osDeallocPages
include genode/alloc # osAllocPages, osTryAllocPages, osDeallocPages
elif defined(posix):
const

View file

@ -116,6 +116,7 @@ when defined(windows):
importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
elif defined(genode):
import genode/env
const
GenodeHeader = "genode_cpp/threads.h"
type
@ -125,11 +126,12 @@ elif defined(genode):
ThreadVarSlot = int
proc initThread(s: var SysThread,
env: GenodeEnv,
stackSize: culonglong,
entry: GenodeThreadProc,
arg: pointer,
affinity: cuint) {.
importcpp: "#.initThread(genodeEnv, @)".}
importcpp: "#.initThread(@)".}
proc threadVarAlloc(): ThreadVarSlot = 0
@ -569,7 +571,7 @@ when hostOS == "windows":
elif defined(genode):
var affinityOffset: cuint = 1
# CPU affinity offset for next thread, safe to roll-over
## CPU affinity offset for next thread, safe to roll-over
proc createThread*[TArg](t: var Thread[TArg],
tp: proc (arg: TArg) {.thread, nimcall.},
@ -580,6 +582,7 @@ elif defined(genode):
t.dataFn = tp
when hasSharedHeap: t.stackSize = ThreadStackSize
t.sys.initThread(
runtimeEnv,
ThreadStackSize.culonglong,
threadProcWrapper[TArg], addr(t), affinityOffset)
inc affinityOffset

View file

@ -44,6 +44,10 @@ else:
const
DLLSSLName* = "libssl" & versions & ".dylib"
DLLUtilName* = "libcrypto" & versions & ".dylib"
elif defined(genode):
const
DLLSSLName* = "libssl.lib.so"
DLLUtilName* = "libcrypto.lib.so"
else:
const
DLLSSLName* = "libssl.so" & versions