From effc6710d97a71f1ffd419ad6e98f8b544b4f44f Mon Sep 17 00:00:00 2001 From: Achilleas Anagnostopoulos Date: Fri, 30 Jun 2017 08:04:10 +0100 Subject: [PATCH] Initialize Go memory allocator --- kernel/goruntime/bootstrap.go | 30 ++++++++++++++++++++++++++++++ kernel/goruntime/bootstrap_test.go | 11 +++++++++++ kernel/kmain/kmain.go | 3 +++ 3 files changed, 44 insertions(+) diff --git a/kernel/goruntime/bootstrap.go b/kernel/goruntime/bootstrap.go index 8e3b63f..e78cc35 100644 --- a/kernel/goruntime/bootstrap.go +++ b/kernel/goruntime/bootstrap.go @@ -5,6 +5,7 @@ package goruntime import ( "unsafe" + "github.com/achilleasa/gopher-os/kernel" "github.com/achilleasa/gopher-os/kernel/mem" "github.com/achilleasa/gopher-os/kernel/mem/pmm/allocator" "github.com/achilleasa/gopher-os/kernel/mem/vmm" @@ -14,8 +15,12 @@ var ( mapFn = vmm.Map earlyReserveRegionFn = vmm.EarlyReserveRegion frameAllocFn = allocator.AllocFrame + mallocInitFn = mallocInit ) +//go:linkname mallocInit runtime.mallocinit +func mallocInit() + //go:linkname mSysStatInc runtime.mSysStatInc func mSysStatInc(*uint64, uintptr) @@ -100,6 +105,30 @@ func sysAlloc(size uintptr, sysStat *uint64) unsafe.Pointer { return unsafe.Pointer(regionStartAddr) } +// nanotime returns a monotonically increasing clock value. This is a dummy +// implementation and will be replaced when the timekeeper package is +// implemented. +// +// This function replaces runtime.nanotime and is invoked by the Go allocator +// when a span allocation is performed. +// +//go:redirect-from runtime.nanotime +//go:nosplit +func nanotime() uint64 { + // Use a dummy loop to prevent the compiler from inlining this function. + for i := 0; i < 100; i++ { + } + return 1 +} + +// Init enables support for various Go runtime features. After a call to init +// the following runtime features become available for use: +// - heap memory allocation (new, make e.t.c) +func Init() *kernel.Error { + mallocInitFn() + return nil +} + func init() { // Dummy calls so the compiler does not optimize away the functions in // this file. @@ -112,4 +141,5 @@ func init() { sysReserve(zeroPtr, 0, &reserved) sysMap(zeroPtr, 0, reserved, &stat) sysAlloc(0, &stat) + stat = nanotime() } diff --git a/kernel/goruntime/bootstrap_test.go b/kernel/goruntime/bootstrap_test.go index 603f123..0ab567f 100644 --- a/kernel/goruntime/bootstrap_test.go +++ b/kernel/goruntime/bootstrap_test.go @@ -235,3 +235,14 @@ func TestSysAlloc(t *testing.T) { } }) } + +func TestInit(t *testing.T) { + defer func() { + mallocInitFn = mallocInit + }() + mallocInitFn = func() {} + + if err := Init(); err != nil { + t.Fatal(t) + } +} diff --git a/kernel/kmain/kmain.go b/kernel/kmain/kmain.go index 2c59342..631d67e 100644 --- a/kernel/kmain/kmain.go +++ b/kernel/kmain/kmain.go @@ -2,6 +2,7 @@ package kmain import ( "github.com/achilleasa/gopher-os/kernel" + "github.com/achilleasa/gopher-os/kernel/goruntime" "github.com/achilleasa/gopher-os/kernel/hal" "github.com/achilleasa/gopher-os/kernel/hal/multiboot" "github.com/achilleasa/gopher-os/kernel/mem/pmm/allocator" @@ -34,6 +35,8 @@ func Kmain(multibootInfoPtr, kernelStart, kernelEnd uintptr) { panic(err) } else if err = vmm.Init(); err != nil { panic(err) + } else if err = goruntime.Init(); err != nil { + panic(err) } // Use kernel.Panic instead of panic to prevent the compiler from