# # # Nim's Runtime Library # (c) Copyright 2017 Emery Hemingway # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # 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 type Map = object attachment: pointer size: int ds: DataspaceCapability SlabMeta = object next: ptr MapSlab ds: DataspaceCapability MapSlab = object meta: SlabMeta maps: array[1,Map] const SlabBackendSize = 4096 proc ramAvail(env: GenodeEnv): int {. importcpp: "#->pd().avail_ram().value".} ## Return number of bytes available for allocation. proc capsAvail(env: GenodeEnv): int {. importcpp: "#->pd().avail_caps().value".} ## Return the number of available capabilities. ## Each dataspace allocation consumes a capability. proc allocDataspace(env: GenodeEnv; size: int): DataspaceCapability {. importcpp: "#->pd().alloc(@)".} ## Allocate a dataspace and its capability. proc attachDataspace(env: GenodeEnv; ds: DataspaceCapability): pointer {. importcpp: "#->rm().attach(@)".} ## Attach a dataspace into the component address-space. proc detachAddress(env: GenodeEnv; p: pointer) {. importcpp: "#->rm().detach(@)".} ## Detach a dataspace from the component address-space. proc freeDataspace(env: GenodeEnv; ds: DataspaceCapability) {. importcpp: "#->pd().free(@)".} ## Free a dataspace. proc newMapSlab(): ptr MapSlab = let ds = runtimeEnv.allocDataspace SlabBackendSize p = runtimeEnv.attachDataspace ds result = cast[ptr MapSlab](p) result.meta.ds = ds iterator items(s: ptr MapSlab): ptr Map = let mapCount = (SlabBackendSize - sizeof(SlabMeta)) div sizeof(Map) for i in 0 .. = size and runtimeEnv.capsAvail() > 4: result = osAllocPages size proc osDeallocPages(p: pointer; size: int) = var slab = slabs while not slab.isNil: # lookup first free spot in slabs for m in slab.items: if m.attachment == p: if m.size != size: echo "cannot partially detach dataspace" quit -1 runtimeEnv.detachAddress m.attachment runtimeEnv.freeDataspace m.ds m[] = Map() return slab = slab.meta.next