]> Cypherpunks.ru repositories - gostls13.git/commitdiff
runtime: add remaining wasip1 files
authorJohan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Sat, 25 Mar 2023 06:11:55 +0000 (23:11 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 6 Apr 2023 17:48:24 +0000 (17:48 +0000)
Implements OS interactions and memory management.

For #58141

Co-authored-by: Richard Musiol <neelance@gmail.com>
Co-authored-by: Achille Roussel <achille.roussel@gmail.com>
Co-authored-by: Julien Fabre <ju.pryz@gmail.com>
Co-authored-by: Evan Phoenix <evan@phx.io>
Change-Id: I876e7b033090c2fe2d76d2535bb63d52efa36185
Reviewed-on: https://go-review.googlesource.com/c/go/+/479618
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

19 files changed:
src/internal/testenv/testenv.go
src/runtime/lock_wasip1.go [new file with mode: 0644]
src/runtime/mem_js.go
src/runtime/mem_wasip1.go [new file with mode: 0644]
src/runtime/mem_wasm.go [new file with mode: 0644]
src/runtime/netpoll.go
src/runtime/netpoll_fake.go
src/runtime/os_js.go
src/runtime/os_wasip1.go [new file with mode: 0644]
src/runtime/os_wasm.go [new file with mode: 0644]
src/runtime/pprof/pprof_test.go
src/runtime/pprof/proto_test.go
src/runtime/runtime_test.go
src/runtime/semasleep_test.go
src/runtime/stubs2.go
src/runtime/stubs3.go
src/runtime/sys_wasm.s
src/runtime/timestub2.go
src/runtime/trace/trace_test.go

index 94cec0b8bdb27f7ec4d8231644f028a4da34d5b0..565230e24c60adac7c039fa64a6cbe18c6deac26 100644 (file)
@@ -78,6 +78,24 @@ func MustHaveGoRun(t testing.TB) {
        }
 }
 
+// HasParallelism reports whether the current system can execute multiple
+// threads in parallel.
+func HasParallelism() bool {
+       switch runtime.GOOS {
+       case "js", "wasip1":
+               return false
+       }
+       return true
+}
+
+// MustHaveParallelism checks that the current system can execute multiple
+// threads in parallel. If not, MustHaveParallelism calls t.Skip with an explanation.
+func MustHaveParallelism(t testing.TB) {
+       if !HasParallelism() {
+               t.Skipf("skipping test: no parallelism available on %s/%s", runtime.GOOS, runtime.GOARCH)
+       }
+}
+
 // GoToolPath reports the path to the Go tool.
 // It is a convenience wrapper around GoTool.
 // If the tool is unavailable GoToolPath calls t.Skip.
diff --git a/src/runtime/lock_wasip1.go b/src/runtime/lock_wasip1.go
new file mode 100644 (file)
index 0000000..c4fc59f
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build wasip1
+
+package runtime
+
+// wasm has no support for threads yet. There is no preemption.
+// See proposal: https://github.com/WebAssembly/threads
+// Waiting for a mutex or timeout is implemented as a busy loop
+// while allowing other goroutines to run.
+
+const (
+       mutex_unlocked = 0
+       mutex_locked   = 1
+
+       active_spin     = 4
+       active_spin_cnt = 30
+)
+
+func lock(l *mutex) {
+       lockWithRank(l, getLockRank(l))
+}
+
+func lock2(l *mutex) {
+       if l.key == mutex_locked {
+               // wasm is single-threaded so we should never
+               // observe this.
+               throw("self deadlock")
+       }
+       gp := getg()
+       if gp.m.locks < 0 {
+               throw("lock count")
+       }
+       gp.m.locks++
+       l.key = mutex_locked
+}
+
+func unlock(l *mutex) {
+       unlockWithRank(l)
+}
+
+func unlock2(l *mutex) {
+       if l.key == mutex_unlocked {
+               throw("unlock of unlocked lock")
+       }
+       gp := getg()
+       gp.m.locks--
+       if gp.m.locks < 0 {
+               throw("lock count")
+       }
+       l.key = mutex_unlocked
+}
+
+// One-time notifications.
+func noteclear(n *note) {
+       n.key = 0
+}
+
+func notewakeup(n *note) {
+       if n.key != 0 {
+               print("notewakeup - double wakeup (", n.key, ")\n")
+               throw("notewakeup - double wakeup")
+       }
+       n.key = 1
+}
+
+func notesleep(n *note) {
+       throw("notesleep not supported by wasi")
+}
+
+func notetsleep(n *note, ns int64) bool {
+       throw("notetsleep not supported by wasi")
+       return false
+}
+
+// same as runtime·notetsleep, but called on user g (not g0)
+func notetsleepg(n *note, ns int64) bool {
+       gp := getg()
+       if gp == gp.m.g0 {
+               throw("notetsleepg on g0")
+       }
+
+       deadline := nanotime() + ns
+       for {
+               if n.key != 0 {
+                       return true
+               }
+               if sched_yield() != 0 {
+                       throw("sched_yield failed")
+               }
+               Gosched()
+               if ns >= 0 && nanotime() >= deadline {
+                       return false
+               }
+       }
+}
+
+func beforeIdle(int64, int64) (*g, bool) {
+       return nil, false
+}
+
+func checkTimeouts() {}
+
+//go:wasmimport wasi_snapshot_preview1 sched_yield
+func sched_yield() errno
index 3aaf6ca5e70046d6ab421d0969a4312e23557a2c..080b1abc6701cc85d695e3ce897f8010d75ffd14 100644 (file)
@@ -2,27 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build js && wasm
+//go:build js
 
 package runtime
 
-import "unsafe"
-
-func sbrk(n uintptr) unsafe.Pointer {
-       grow := divRoundUp(n, physPageSize)
-       size := currentMemory()
-
-       if growMemory(int32(grow)) < 0 {
-               return nil
-       }
-
-       resetMemoryDataView()
-       return unsafe.Pointer(uintptr(size) * physPageSize)
-}
-
-func currentMemory() int32
-func growMemory(pages int32) int32
-
 // resetMemoryDataView signals the JS front-end that WebAssembly's memory.grow instruction has been used.
 // This allows the front-end to replace the old DataView object with a new one.
 //
diff --git a/src/runtime/mem_wasip1.go b/src/runtime/mem_wasip1.go
new file mode 100644 (file)
index 0000000..41ffa0d
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build wasip1
+
+package runtime
+
+func resetMemoryDataView() {
+       // This function is a no-op on WASI, it is only used to notify the browser
+       // that its view of the WASM memory needs to be updated when compiling for
+       // GOOS=js.
+}
diff --git a/src/runtime/mem_wasm.go b/src/runtime/mem_wasm.go
new file mode 100644 (file)
index 0000000..d9d3270
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+func sbrk(n uintptr) unsafe.Pointer {
+       grow := divRoundUp(n, physPageSize)
+       size := growMemory(int32(grow))
+       if size < 0 {
+               return nil
+       }
+       resetMemoryDataView()
+       return unsafe.Pointer(uintptr(size) * physPageSize)
+}
+
+// Implemented in src/runtime/sys_wasm.s
+func growMemory(pages int32) int32
index 5ac1f37048c080908deb2bc1a83134ce4ecd5035..b4eb7330c37192a4e71bdb93b20a586775249325 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build unix || (js && wasm) || windows
+//go:build unix || (js && wasm) || wasip1 || windows
 
 package runtime
 
index de1dcae7acf8123e8a1dc0fe3ab2634a6d289960..5782c7851510b077d61bc386f9351f4dd01135e3 100644 (file)
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Fake network poller for wasm/js.
-// Should never be used, because wasm/js network connections do not honor "SetNonblock".
+// Fake network poller for js/wasm and wasip1/wasm.
+// Should never be used, because wasm network connections do not honor "SetNonblock".
 
-//go:build js && wasm
+//go:build (js && wasm) || wasip1
 
 package runtime
 
index 20ac524552cb5a52bbcaa1110ec58784b04c4327..65fb499de676dcced1b4235d2035f08c7fd3bc8c 100644 (file)
@@ -7,7 +7,6 @@
 package runtime
 
 import (
-       "runtime/internal/atomic"
        "unsafe"
 )
 
@@ -21,154 +20,18 @@ func write1(fd uintptr, p unsafe.Pointer, n int32) int32 {
        return n
 }
 
-// Stubs so tests can link correctly. These should never be called.
-func open(name *byte, mode, perm int32) int32        { panic("not implemented") }
-func closefd(fd int32) int32                         { panic("not implemented") }
-func read(fd int32, p unsafe.Pointer, n int32) int32 { panic("not implemented") }
-
 //go:wasmimport gojs runtime.wasmWrite
 //go:noescape
 func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
 
-func usleep(usec uint32)
-
-//go:nosplit
-func usleep_no_g(usec uint32) {
-       usleep(usec)
-}
-
-func exitThread(wait *atomic.Uint32)
-
-type mOS struct{}
-
-func osyield()
-
-//go:nosplit
-func osyield_no_g() {
-       osyield()
-}
-
-const _SIGSEGV = 0xb
-
-func sigpanic() {
-       gp := getg()
-       if !canpanic() {
-               throw("unexpected signal during runtime execution")
-       }
-
-       // js only invokes the exception handler for memory faults.
-       gp.sig = _SIGSEGV
-       panicmem()
-}
-
-type sigset struct{}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
-func mpreinit(mp *m) {
-       mp.gsignal = malg(32 * 1024)
-       mp.gsignal.m = mp
-}
-
-//go:nosplit
-func sigsave(p *sigset) {
-}
-
-//go:nosplit
-func msigrestore(sigmask sigset) {
-}
-
-//go:nosplit
-//go:nowritebarrierrec
-func clearSignalHandlers() {
-}
-
-//go:nosplit
-func sigblock(exiting bool) {
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the new thread, cannot allocate memory.
-func minit() {
-}
-
-// Called from dropm to undo the effect of an minit.
-func unminit() {
-}
-
-// Called from exitm, but not from drop, to undo the effect of thread-owned
-// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
-func mdestroy(mp *m) {
-}
-
-func osinit() {
-       // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
-       physPageSize = 64 * 1024
-       initBloc()
-       ncpu = 1
-       getg().m.procid = 2
-}
-
-// wasm has no signals
-const _NSIG = 0
-
-func signame(sig uint32) string {
-       return ""
-}
-
-func crash() {
-       *(*int32)(nil) = 0
+func usleep(usec uint32) {
+       // TODO(neelance): implement usleep
 }
 
 //go:wasmimport gojs runtime.getRandomData
+//go:noescape
 func getRandomData(r []byte)
 
 func goenvs() {
        goenvs_unix()
 }
-
-func initsig(preinit bool) {
-}
-
-// May run with m.p==nil, so write barriers are not allowed.
-//
-//go:nowritebarrier
-func newosproc(mp *m) {
-       throw("newosproc: not implemented")
-}
-
-func setProcessCPUProfiler(hz int32) {}
-func setThreadCPUProfiler(hz int32)  {}
-func sigdisable(uint32)              {}
-func sigenable(uint32)               {}
-func sigignore(uint32)               {}
-
-//go:linkname os_sigpipe os.sigpipe
-func os_sigpipe() {
-       throw("too many writes on closed pipe")
-}
-
-//go:nosplit
-func cputicks() int64 {
-       // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
-       // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
-       return nanotime()
-}
-
-//go:linkname syscall_now syscall.now
-func syscall_now() (sec int64, nsec int32) {
-       sec, nsec, _ = time_now()
-       return
-}
-
-// gsignalStack is unused on js.
-type gsignalStack struct{}
-
-const preemptMSupported = false
-
-func preemptM(mp *m) {
-       // No threads, so nothing to do.
-}
-
-// getcallerfp returns the address of the frame pointer in the callers frame or 0 if not implemented.
-func getcallerfp() uintptr { return 0 }
diff --git a/src/runtime/os_wasip1.go b/src/runtime/os_wasip1.go
new file mode 100644 (file)
index 0000000..cd02a18
--- /dev/null
@@ -0,0 +1,251 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build wasip1
+
+package runtime
+
+import "unsafe"
+
+// GOARCH=wasm currently has 64 bits pointers, but the WebAssembly host expects
+// pointers to be 32 bits so we use this type alias to represent pointers in
+// structs and arrays passed as arguments to WASI functions.
+//
+// Note that the use of an integer type prevents the compiler from tracking
+// pointers passed to WASI functions, so we must use KeepAlive to explicitly
+// retain the objects that could otherwise be reclaimed by the GC.
+type uintptr32 = uint32
+
+// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-size-u32
+type size = uint32
+
+// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-errno-variant
+type errno = uint32
+
+// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-filesize-u64
+type filesize = uint64
+
+// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-timestamp-u64
+type timestamp = uint64
+
+// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-clockid-variant
+type clockid = uint32
+
+const (
+       clockRealtime  clockid = 0
+       clockMonotonic clockid = 1
+)
+
+// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-iovec-record
+type iovec struct {
+       buf    uintptr32
+       bufLen size
+}
+
+//go:wasmimport wasi_snapshot_preview1 proc_exit
+func exit(code int32)
+
+//go:wasmimport wasi_snapshot_preview1 args_get
+//go:noescape
+func args_get(argv *uintptr32, argvBuf *byte) errno
+
+//go:wasmimport wasi_snapshot_preview1 args_sizes_get
+//go:noescape
+func args_sizes_get(argc *size, argvBufLen *size) errno
+
+//go:wasmimport wasi_snapshot_preview1 clock_time_get
+//go:noescape
+func clock_time_get(clock_id clockid, precision timestamp, time *timestamp) errno
+
+//go:wasmimport wasi_snapshot_preview1 environ_get
+//go:noescape
+func environ_get(environ *uintptr32, environBuf *byte) errno
+
+//go:wasmimport wasi_snapshot_preview1 environ_sizes_get
+//go:noescape
+func environ_sizes_get(environCount *size, environBufLen *size) errno
+
+//go:wasmimport wasi_snapshot_preview1 fd_write
+//go:noescape
+func fd_write(fd int32, iovs *iovec, iovsLen size, nwritten *size) errno
+
+//go:wasmimport wasi_snapshot_preview1 random_get
+//go:noescape
+func random_get(buf *byte, bufLen size) errno
+
+type eventtype = uint8
+
+const (
+       eventtypeClock eventtype = iota
+       eventtypeFdRead
+       eventtypeFdWrite
+)
+
+type eventrwflags = uint16
+
+const (
+       fdReadwriteHangup eventrwflags = 1 << iota
+)
+
+type userdata = uint64
+
+// The go:wasmimport directive currently does not accept values of type uint16
+// in arguments or returns of the function signature. Most WASI imports return
+// an errno value, which we have to define as uint32 because of that limitation.
+// However, the WASI errno type is intended to be a 16 bits integer, and in the
+// event struct the error field should be of type errno. If we used the errno
+// type for the error field it would result in a mismatching field alignment and
+// struct size because errno is declared as a 32 bits type, so we declare the
+// error field as a plain uint16.
+type event struct {
+       userdata    userdata
+       error       uint16
+       typ         eventtype
+       fdReadwrite eventFdReadwrite
+}
+
+type eventFdReadwrite struct {
+       nbytes filesize
+       flags  eventrwflags
+}
+
+type subclockflags = uint16
+
+const (
+       subscriptionClockAbstime subclockflags = 1 << iota
+)
+
+type subscriptionClock struct {
+       id        clockid
+       timeout   timestamp
+       precision timestamp
+       flags     subclockflags
+}
+
+type subscription struct {
+       userdata userdata
+       u        subscriptionUnion
+}
+
+type subscriptionUnion [5]uint64
+
+func (u *subscriptionUnion) eventtype() *eventtype {
+       return (*eventtype)(unsafe.Pointer(&u[0]))
+}
+
+func (u *subscriptionUnion) subscriptionClock() *subscriptionClock {
+       return (*subscriptionClock)(unsafe.Pointer(&u[1]))
+}
+
+//go:wasmimport wasi_snapshot_preview1 poll_oneoff
+//go:noescape
+func poll_oneoff(in *subscription, out *event, nsubscriptions size, nevents *size) errno
+
+func write1(fd uintptr, p unsafe.Pointer, n int32) int32 {
+       iov := iovec{
+               buf:    uintptr32(uintptr(p)),
+               bufLen: size(n),
+       }
+       var nwritten size
+       if fd_write(int32(fd), &iov, 1, &nwritten) != 0 {
+               throw("fd_write failed")
+       }
+       return int32(nwritten)
+}
+
+func usleep(usec uint32) {
+       var in subscription
+       var out event
+       var nevents size
+
+       eventtype := in.u.eventtype()
+       *eventtype = eventtypeClock
+
+       subscription := in.u.subscriptionClock()
+       subscription.id = clockMonotonic
+       subscription.timeout = timestamp(usec) * 1e3
+       subscription.precision = 1e3
+
+       if poll_oneoff(&in, &out, 1, &nevents) != 0 {
+               throw("wasi_snapshot_preview1.poll_oneoff")
+       }
+}
+
+func getRandomData(r []byte) {
+       if random_get(&r[0], size(len(r))) != 0 {
+               throw("random_get failed")
+       }
+}
+
+func goenvs() {
+       // arguments
+       var argc size
+       var argvBufLen size
+       if args_sizes_get(&argc, &argvBufLen) != 0 {
+               throw("args_sizes_get failed")
+       }
+
+       argslice = make([]string, argc)
+       if argc > 0 {
+               argv := make([]uintptr32, argc)
+               argvBuf := make([]byte, argvBufLen)
+               if args_get(&argv[0], &argvBuf[0]) != 0 {
+                       throw("args_get failed")
+               }
+
+               for i := range argslice {
+                       start := argv[i] - uintptr32(uintptr(unsafe.Pointer(&argvBuf[0])))
+                       end := start
+                       for argvBuf[end] != 0 {
+                               end++
+                       }
+                       argslice[i] = string(argvBuf[start:end])
+               }
+       }
+
+       // environment
+       var environCount size
+       var environBufLen size
+       if environ_sizes_get(&environCount, &environBufLen) != 0 {
+               throw("environ_sizes_get failed")
+       }
+
+       envs = make([]string, environCount)
+       if environCount > 0 {
+               environ := make([]uintptr32, environCount)
+               environBuf := make([]byte, environBufLen)
+               if environ_get(&environ[0], &environBuf[0]) != 0 {
+                       throw("environ_get failed")
+               }
+
+               for i := range envs {
+                       start := environ[i] - uintptr32(uintptr(unsafe.Pointer(&environBuf[0])))
+                       end := start
+                       for environBuf[end] != 0 {
+                               end++
+                       }
+                       envs[i] = string(environBuf[start:end])
+               }
+       }
+}
+
+func walltime() (sec int64, nsec int32) {
+       return walltime1()
+}
+
+func walltime1() (sec int64, nsec int32) {
+       var time timestamp
+       if clock_time_get(clockRealtime, 0, &time) != 0 {
+               throw("clock_time_get failed")
+       }
+       return int64(time / 1000000000), int32(time % 1000000000)
+}
+
+func nanotime1() int64 {
+       var time timestamp
+       if clock_time_get(clockMonotonic, 0, &time) != 0 {
+               throw("clock_time_get failed")
+       }
+       return int64(time)
+}
diff --git a/src/runtime/os_wasm.go b/src/runtime/os_wasm.go
new file mode 100644 (file)
index 0000000..1a6f7d8
--- /dev/null
@@ -0,0 +1,152 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "runtime/internal/atomic"
+       "unsafe"
+)
+
+func osinit() {
+       // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
+       physPageSize = 64 * 1024
+       initBloc()
+       ncpu = 1
+       getg().m.procid = 2
+}
+
+const _SIGSEGV = 0xb
+
+func sigpanic() {
+       gp := getg()
+       if !canpanic() {
+               throw("unexpected signal during runtime execution")
+       }
+
+       // js only invokes the exception handler for memory faults.
+       gp.sig = _SIGSEGV
+       panicmem()
+}
+
+// func exitThread(wait *uint32)
+// FIXME: wasm doesn't have atomic yet
+func exitThread(wait *atomic.Uint32)
+
+type mOS struct{}
+
+func osyield()
+
+//go:nosplit
+func osyield_no_g() {
+       osyield()
+}
+
+type sigset struct{}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+//go:nosplit
+func usleep_no_g(usec uint32) {
+       usleep(usec)
+}
+
+//go:nosplit
+func sigsave(p *sigset) {
+}
+
+//go:nosplit
+func msigrestore(sigmask sigset) {
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func clearSignalHandlers() {
+}
+
+//go:nosplit
+func sigblock(exiting bool) {
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, cannot allocate memory.
+func minit() {
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+}
+
+// Called from exitm, but not from drop, to undo the effect of thread-owned
+// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
+func mdestroy(mp *m) {
+}
+
+// wasm has no signals
+const _NSIG = 0
+
+func signame(sig uint32) string {
+       return ""
+}
+
+func crash() {
+       *(*int32)(nil) = 0
+}
+
+func initsig(preinit bool) {
+}
+
+// May run with m.p==nil, so write barriers are not allowed.
+//
+//go:nowritebarrier
+func newosproc(mp *m) {
+       throw("newosproc: not implemented")
+}
+
+//go:linkname os_sigpipe os.sigpipe
+func os_sigpipe() {
+       throw("too many writes on closed pipe")
+}
+
+//go:linkname syscall_now syscall.now
+func syscall_now() (sec int64, nsec int32) {
+       sec, nsec, _ = time_now()
+       return
+}
+
+//go:nosplit
+func cputicks() int64 {
+       // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
+       // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+       // TODO: need more entropy to better seed fastrand.
+       return nanotime()
+}
+
+// gsignalStack is unused on js.
+type gsignalStack struct{}
+
+const preemptMSupported = false
+
+func preemptM(mp *m) {
+       // No threads, so nothing to do.
+}
+
+// getcallerfp returns the address of the frame pointer in the callers frame or 0 if not implemented.
+func getcallerfp() uintptr { return 0 }
+
+func setProcessCPUProfiler(hz int32) {}
+func setThreadCPUProfiler(hz int32)  {}
+func sigdisable(uint32)              {}
+func sigenable(uint32)               {}
+func sigignore(uint32)               {}
+
+// Stubs so tests can link correctly. These should never be called.
+func open(name *byte, mode, perm int32) int32        { panic("not implemented") }
+func closefd(fd int32) int32                         { panic("not implemented") }
+func read(fd int32, p unsafe.Pointer, n int32) int32 { panic("not implemented") }
index b19ac16170a969c2a4009c2f9c4205accf5ef440..56ba6d98031117f4c98cdbca960e8b81a0c0056d 100644 (file)
@@ -448,6 +448,8 @@ func testCPUProfile(t *testing.T, matches profileMatchFunc, f func(dur time.Dura
                t.Logf("uname -a: %v", vers)
        case "plan9":
                t.Skip("skipping on plan9")
+       case "wasip1":
+               t.Skip("skipping on wasip1")
        }
 
        broken := cpuProfilingBroken()
@@ -1457,6 +1459,8 @@ func containsCountsLabels(prof *profile.Profile, countLabels map[int64]map[strin
 }
 
 func TestGoroutineProfileConcurrency(t *testing.T) {
+       testenv.MustHaveParallelism(t)
+
        goroutineProf := Lookup("goroutine")
 
        profilerCalls := func(s string) int {
@@ -1785,6 +1789,7 @@ func TestCPUProfileLabel(t *testing.T) {
 }
 
 func TestLabelRace(t *testing.T) {
+       testenv.MustHaveParallelism(t)
        // Test the race detector annotations for synchronization
        // between setting labels and consuming them from the
        // profile.
@@ -1809,6 +1814,7 @@ func TestLabelRace(t *testing.T) {
 }
 
 func TestGoroutineProfileLabelRace(t *testing.T) {
+       testenv.MustHaveParallelism(t)
        // Test the race detector annotations for synchronization
        // between setting labels and consuming them from the
        // goroutine profile. See issue #50292.
index e05a1a60a7d98adbdb687f5616333acbbe24f7b4..8ec9c9109a0f129ec19ffbddb41a9e21bc20a87c 100644 (file)
@@ -131,7 +131,7 @@ func testPCs(t *testing.T) (addr1, addr2 uint64, map1, map2 *profile.Mapping) {
                        BuildID:      peBuildID(exe),
                        HasFunctions: true,
                }
-       case "js":
+       case "js", "wasip1":
                addr1 = uint64(abi.FuncPCABIInternal(f1))
                addr2 = uint64(abi.FuncPCABIInternal(f2))
        default:
index 2faf06e2b9fca4297595a1677c07edf3046dfbdb..0839cd96b73e6e9834026e895cd80e24d8716c41 100644 (file)
@@ -207,8 +207,8 @@ func TestSetPanicOnFault(t *testing.T) {
 //
 //go:nocheckptr
 func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) {
-       if GOOS == "js" {
-               t.Skip("js does not support catching faults")
+       if GOOS == "js" || GOOS == "wasip1" {
+               t.Skip(GOOS + " does not support catching faults")
        }
 
        defer func() {
index 726285346555d5738d2841731ef6ac71629bcd09..711d5df7352565d2a01c5bee45e33044e436363d 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !plan9 && !windows && !js
+//go:build !plan9 && !windows && !js && !wasip1
 
 package runtime_test
 
index 0d83deb2aff235173510564ab1624fb055f6c0a6..9637347a35558950a405019f23d1a876878bd2fc 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !aix && !darwin && !js && !openbsd && !plan9 && !solaris && !windows
+//go:build !aix && !darwin && !js && !openbsd && !plan9 && !solaris && !wasip1 && !windows
 
 package runtime
 
index 95306971b4ba256f2ea0b349b2b1d6cba4977724..c3749f34eddac484519b04a749eb2572dce7c8f3 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !aix && !darwin && !freebsd && !openbsd && !plan9 && !solaris
+//go:build !aix && !darwin && !freebsd && !openbsd && !plan9 && !solaris && !wasip1
 
 package runtime
 
index bd60e1d419be964555a44100f0dd2626838c9b85..1e73adadd56aa78bf25b35b14104cba3d175d8fc 100644 (file)
@@ -86,15 +86,6 @@ TEXT runtime·exitThread(SB), NOSPLIT, $0-0
 TEXT runtime·osyield(SB), NOSPLIT, $0-0
        UNDEF
 
-TEXT runtime·usleep(SB), NOSPLIT, $0-0
-       RET // TODO(neelance): implement usleep
-
-TEXT runtime·currentMemory(SB), NOSPLIT, $0
-       Get SP
-       CurrentMemory
-       I32Store ret+0(FP)
-       RET
-
 TEXT runtime·growMemory(SB), NOSPLIT, $0
        Get SP
        I32Load pages+0(FP)
index b0eae502daeac15f1b4a9cacc20fdfa02e147859..49bfeb60c88de2e8aa1c80e7ce30a0df07513ddd 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !windows && !(linux && amd64)
+//go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !wasip1 && !windows && !(linux && amd64)
 
 package runtime
 
index 1203e34a58b50dab4fd842e0a2a0be359ea9c155..04a43a05f4535f2f4afbc3233c15135901df5d11 100644 (file)
@@ -184,8 +184,9 @@ func testBrokenTimestamps(t *testing.T, data []byte) {
 }
 
 func TestTraceStress(t *testing.T) {
-       if runtime.GOOS == "js" {
-               t.Skip("no os.Pipe on js")
+       switch runtime.GOOS {
+       case "js", "wasip1":
+               t.Skip("no os.Pipe on " + runtime.GOOS)
        }
        if IsEnabled() {
                t.Skip("skipping because -test.trace is set")
@@ -348,8 +349,9 @@ func isMemoryConstrained() bool {
 // Do a bunch of various stuff (timers, GC, network, etc) in a separate goroutine.
 // And concurrently with all that start/stop trace 3 times.
 func TestTraceStressStartStop(t *testing.T) {
-       if runtime.GOOS == "js" {
-               t.Skip("no os.Pipe on js")
+       switch runtime.GOOS {
+       case "js", "wasip1":
+               t.Skip("no os.Pipe on " + runtime.GOOS)
        }
        if IsEnabled() {
                t.Skip("skipping because -test.trace is set")