Merge branch 'dev' into feature/usb-common

This commit is contained in:
ardnew
2021-08-02 13:39:59 -05:00
254 changed files with 4461 additions and 531 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
// +build arm,!baremetal,!wasm arm,arm7tdmi
// +build arm,!baremetal,!tinygo.wasm arm,arm7tdmi
package runtime
+107
View File
@@ -0,0 +1,107 @@
// +build tinygo.wasm
package runtime
import (
"unsafe"
)
const GOARCH = "wasm"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
//go:extern __heap_base
var heapStartSymbol [0]byte
//go:extern __global_base
var globalsStartSymbol [0]byte
//export llvm.wasm.memory.size.i32
func wasm_memory_size(index int32) int32
//export llvm.wasm.memory.grow.i32
func wasm_memory_grow(index int32, delta int32) int32
var (
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
)
const wasmPageSize = 64 * 1024
func align(ptr uintptr) uintptr {
// Align to 16, which is the alignment of max_align_t:
// https://godbolt.org/z/dYqTsWrGq
const heapAlign = 16
return (ptr + heapAlign - 1) &^ (heapAlign - 1)
}
func getCurrentStackPointer() uintptr
// growHeap tries to grow the heap size. It returns true if it succeeds, false
// otherwise.
func growHeap() bool {
// Grow memory by the available size, which means the heap size is doubled.
memorySize := wasm_memory_size(0)
result := wasm_memory_grow(0, memorySize)
if result == -1 {
// Grow failed.
return false
}
setHeapEnd(uintptr(wasm_memory_size(0) * wasmPageSize))
// Heap has grown successfully.
return true
}
// The below functions override the default allocator of wasi-libc.
// Most functions are defined but unimplemented to make sure that if there is
// any code using them, they will get an error instead of (incorrectly) using
// the wasi-libc dlmalloc heap implementation instead. If they are needed by any
// program, they can certainly be implemented.
//export malloc
func libc_malloc(size uintptr) unsafe.Pointer {
return alloc(size)
}
//export free
func libc_free(ptr unsafe.Pointer) {
free(ptr)
}
//export calloc
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
// Note: we could be even more correct here and check that nmemb * size
// doesn't overflow. However the current implementation should normally work
// fine.
return alloc(nmemb * size)
}
//export realloc
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
runtimePanic("unimplemented: realloc")
return nil
}
//export posix_memalign
func libc_posix_memalign(memptr *unsafe.Pointer, alignment, size uintptr) int {
runtimePanic("unimplemented: posix_memalign")
return 0
}
//export aligned_alloc
func libc_aligned_alloc(alignment, bytes uintptr) unsafe.Pointer {
runtimePanic("unimplemented: aligned_alloc")
return nil
}
//export malloc_usable_size
func libc_malloc_usable_size(ptr unsafe.Pointer) uintptr {
runtimePanic("unimplemented: malloc_usable_size")
return 0
}
-57
View File
@@ -1,57 +0,0 @@
// +build wasm
package runtime
import (
"unsafe"
)
const GOARCH = "wasm"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
//go:extern __heap_base
var heapStartSymbol [0]byte
//go:extern __global_base
var globalsStartSymbol [0]byte
//export llvm.wasm.memory.size.i32
func wasm_memory_size(index int32) int32
//export llvm.wasm.memory.grow.i32
func wasm_memory_grow(index int32, delta int32) int32
var (
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
)
const wasmPageSize = 64 * 1024
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 3) &^ 3
}
func getCurrentStackPointer() uintptr
// growHeap tries to grow the heap size. It returns true if it succeeds, false
// otherwise.
func growHeap() bool {
// Grow memory by the available size, which means the heap size is doubled.
memorySize := wasm_memory_size(0)
result := wasm_memory_grow(0, memorySize)
if result == -1 {
// Grow failed.
return false
}
setHeapEnd(uintptr(wasm_memory_size(0) * wasmPageSize))
// Heap has grown successfully.
return true
}
+21
View File
@@ -52,3 +52,24 @@ func syscall_Exit(code int) {
}
const baremetal = true
// timeOffset is how long the monotonic clock started after the Unix epoch. It
// should be a positive integer under normal operation or zero when it has not
// been set.
var timeOffset int64
//go:linkname now time.now
func now() (sec int64, nsec int32, mono int64) {
mono = nanotime()
sec = (mono + timeOffset) / (1000 * 1000 * 1000)
nsec = int32((mono + timeOffset) - sec*(1000*1000*1000))
return
}
// AdjustTimeOffset adds the given offset to the built-in time offset. A
// positive value adds to the time (skipping some time), a negative value moves
// the clock into the past.
func AdjustTimeOffset(offset int64) {
// TODO: do this atomically?
timeOffset += offset
}
+5
View File
@@ -0,0 +1,5 @@
package runtime
func Callers(skip int, pc []uintptr) int {
return 0
}
+9 -1
View File
@@ -51,7 +51,7 @@ const (
)
var (
metadataStart unsafe.Pointer // pointer to the start of the heap
metadataStart unsafe.Pointer // pointer to the start of the heap metadata
nextAlloc gcBlock // the next block that should be tried by the allocator
endBlock gcBlock // the block just past the end of the available space
)
@@ -228,6 +228,14 @@ func setHeapEnd(newHeapEnd uintptr) {
// This function can be called again when the heap size increases. The caller is
// responsible for copying the metadata to the new location.
func calculateHeapAddresses() {
if GOARCH == "wasm" {
// This is a workaround for a bug in wasm-ld: wasm-ld doesn't always
// align __heap_base and when this memory is shared through an API, it
// might result in unaligned memory. For details, see:
// https://reviews.llvm.org/D106499
// It should be removed once we switch to LLVM 13, where this is fixed.
heapStart = align(heapStart)
}
totalSize := heapEnd - heapStart
// Allocate some memory to keep 2 bits of information about every block.
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative gc.extalloc
// +build baremetal wasm
// +build baremetal tinygo.wasm
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative gc.extalloc
// +build !baremetal,!wasm
// +build !baremetal,!tinygo.wasm
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative gc.extalloc
// +build wasm
// +build tinygo.wasm
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative gc.extalloc
// +build !wasm
// +build !tinygo.wasm
package runtime
+69
View File
@@ -0,0 +1,69 @@
// +build gc.conservative
package runtime
// Memory statistics
// Subset of memory statistics from upstream Go.
// Works with conservative gc only.
// A MemStats records statistics about the memory allocator.
type MemStats struct {
// General statistics.
// Sys is the total bytes of memory obtained from the OS.
//
// Sys is the sum of the XSys fields below. Sys measures the
// address space reserved by the runtime for the
// heap, stacks, and other internal data structures.
Sys uint64
// Heap memory statistics.
// HeapSys is bytes of heap memory, total.
//
// In TinyGo unlike upstream Go, we make no distinction between
// regular heap blocks used by escaped-to-the-heap variables and
// blocks occupied by goroutine stacks,
// all such blocks are marked as in-use, see HeapInuse below.
HeapSys uint64
// HeapIdle is bytes in idle (unused) blocks.
HeapIdle uint64
// HeapInuse is bytes in in-use blocks.
HeapInuse uint64
// HeapReleased is bytes of physical memory returned to the OS.
HeapReleased uint64
// Off-heap memory statistics.
//
// The following statistics measure runtime-internal
// structures that are not allocated from heap memory (usually
// because they are part of implementing the heap).
// GCSys is bytes of memory in garbage collection metadata.
GCSys uint64
}
// ReadMemStats populates m with memory statistics.
//
// The returned memory statistics are up to date as of the
// call to ReadMemStats. This would not do GC implicitly for you.
func ReadMemStats(m *MemStats) {
m.HeapIdle = 0
m.HeapInuse = 0
for block := gcBlock(0); block < endBlock; block++ {
bstate := block.state()
if bstate == blockStateFree {
m.HeapIdle += uint64(bytesPerBlock)
} else {
m.HeapInuse += uint64(bytesPerBlock)
}
}
m.HeapReleased = 0 // always 0, we don't currently release memory back to the OS.
m.HeapSys = m.HeapInuse + m.HeapIdle
m.GCSys = uint64(heapEnd - uintptr(metadataStart))
m.Sys = uint64(heapEnd - heapStart)
}
+6
View File
@@ -11,3 +11,9 @@ const (
flag_MAP_PRIVATE = 0x2
flag_MAP_ANONYMOUS = 0x1000 // MAP_ANON
)
// Source: https://opensource.apple.com/source/Libc/Libc-1439.100.3/include/time.h.auto.html
const (
clock_REALTIME = 0
clock_MONOTONIC_RAW = 4
)
+6
View File
@@ -11,3 +11,9 @@ const (
flag_MAP_PRIVATE = 0x2
flag_MAP_ANONYMOUS = 0x20
)
// Source: https://github.com/torvalds/linux/blob/master/include/uapi/linux/time.h
const (
clock_REALTIME = 0
clock_MONOTONIC_RAW = 4
)
-21
View File
@@ -68,27 +68,6 @@ func nanotime() int64 {
return ticksToNanoseconds(ticks())
}
// timeOffset is how long the monotonic clock started after the Unix epoch. It
// should be a positive integer under normal operation or zero when it has not
// been set.
var timeOffset int64
//go:linkname now time.now
func now() (sec int64, nsec int32, mono int64) {
mono = nanotime()
sec = (mono + timeOffset) / (1000 * 1000 * 1000)
nsec = int32((mono + timeOffset) - sec*(1000*1000*1000))
return
}
// AdjustTimeOffset adds the given offset to the built-in time offset. A
// positive value adds to the time (skipping some time), a negative value moves
// the clock into the past.
func AdjustTimeOffset(offset int64) {
// TODO: do this atomically?
timeOffset += offset
}
// Copied from the Go runtime source code.
//go:linkname os_sigpipe os.sigpipe
func os_sigpipe() {
+5 -3
View File
@@ -10,6 +10,9 @@ import (
//export sd_app_evt_wait
func sd_app_evt_wait()
// This is a global variable to avoid a heap allocation in waitForEvents.
var softdeviceEnabled uint8
func waitForEvents() {
// Call into the SoftDevice to sleep. This is necessary here because a
// normal wfe will not put the chip in low power mode (it still consumes
@@ -18,10 +21,9 @@ func waitForEvents() {
// First check whether the SoftDevice is enabled. Unfortunately,
// sd_app_evt_wait cannot be called when the SoftDevice is not enabled.
var enabled uint8
arm.SVCall1(0x12, &enabled) // sd_softdevice_is_enabled
arm.SVCall1(0x12, &softdeviceEnabled) // sd_softdevice_is_enabled
if enabled != 0 {
if softdeviceEnabled != 0 {
// Now pick the appropriate SVCall number. Hopefully they won't change
// in the future with a different SoftDevice version.
if nrf.Device == "nrf51" {
+5
View File
@@ -4,6 +4,8 @@ package runtime
import (
"device/arm"
"machine"
)
// machineTicks is provided by package machine.
@@ -39,6 +41,7 @@ func waitForEvents() {
}
func putchar(c byte) {
machine.Serial.WriteByte(c)
}
// machineInit is provided by package machine.
@@ -46,6 +49,8 @@ func machineInit()
func init() {
machineInit()
machine.Serial.Configure(machine.UARTConfig{})
}
func postinit() {}
@@ -1,4 +1,4 @@
// +build wasm
// +build tinygo.wasm
package runtime
@@ -50,6 +50,14 @@ func putchar(c byte) {
}
}
//go:linkname now time.now
func now() (sec int64, nsec int32, mono int64) {
mono = nanotime()
sec = mono / (1000 * 1000 * 1000)
nsec = int32(mono - sec*(1000*1000*1000))
return
}
// Abort executes the wasm 'unreachable' instruction.
func abort() {
trap()
+17 -7
View File
@@ -38,8 +38,6 @@ type timespec struct {
tv_nsec int // long: on Linux and macOS, follows the platform bitness
}
const CLOCK_MONOTONIC_RAW = 4
var stackTop uintptr
func postinit() {}
@@ -138,19 +136,31 @@ func sleepTicks(d timeUnit) {
usleep(uint(d) / 1000)
}
// Return monotonic time in nanoseconds.
//
// TODO: noescape
func monotime() uint64 {
func getTime(clock int32) uint64 {
ts := timespec{}
clock_gettime(CLOCK_MONOTONIC_RAW, &ts)
clock_gettime(clock, &ts)
return uint64(ts.tv_sec)*1000*1000*1000 + uint64(ts.tv_nsec)
}
// Return monotonic time in nanoseconds.
func monotime() uint64 {
return getTime(clock_MONOTONIC_RAW)
}
func ticks() timeUnit {
return timeUnit(monotime())
}
//go:linkname now time.now
func now() (sec int64, nsec int32, mono int64) {
ts := timespec{}
clock_gettime(clock_REALTIME, &ts)
sec = int64(ts.tv_sec)
nsec = int32(ts.tv_nsec)
mono = nanotime()
return
}
//go:linkname syscall_Exit syscall.Exit
func syscall_Exit(code int) {
exit(code)
+1 -1
View File
@@ -1,4 +1,4 @@
// +build wasm,wasi
// +build tinygo.wasm,wasi
package runtime
+1 -1
View File
@@ -88,7 +88,7 @@ func addSleepTask(t *task.Task, duration timeUnit) {
panic("runtime: addSleepTask: expected next task to be nil")
}
}
t.Data = uint(duration) // TODO: longer durations
t.Data = uint64(duration)
now := ticks()
if sleepQueue == nil {
scheduleLog(" -> sleep new queue")
+20
View File
@@ -0,0 +1,20 @@
package runtime
type Frames struct {
//
}
type Frame struct {
Function string
File string
Line int
}
func CallersFrames(callers []uintptr) *Frames {
return nil
}
func (ci *Frames) Next() (frame Frame, more bool) {
return Frame{}, false
}