github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/lock_wasip1.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build wasip1
     6  
     7  package runtime
     8  
     9  // wasm has no support for threads yet. There is no preemption.
    10  // See proposal: https://github.com/WebAssembly/threads
    11  // Waiting for a mutex or timeout is implemented as a busy loop
    12  // while allowing other goroutines to run.
    13  
    14  const (
    15  	mutex_unlocked = 0
    16  	mutex_locked   = 1
    17  
    18  	active_spin     = 4
    19  	active_spin_cnt = 30
    20  )
    21  
    22  func lock(l *mutex) {
    23  	lockWithRank(l, getLockRank(l))
    24  }
    25  
    26  func lock2(l *mutex) {
    27  	if l.key == mutex_locked {
    28  		// wasm is single-threaded so we should never
    29  		// observe this.
    30  		throw("self deadlock")
    31  	}
    32  	gp := getg()
    33  	if gp.m.locks < 0 {
    34  		throw("lock count")
    35  	}
    36  	gp.m.locks++
    37  	l.key = mutex_locked
    38  }
    39  
    40  func unlock(l *mutex) {
    41  	unlockWithRank(l)
    42  }
    43  
    44  func unlock2(l *mutex) {
    45  	if l.key == mutex_unlocked {
    46  		throw("unlock of unlocked lock")
    47  	}
    48  	gp := getg()
    49  	gp.m.locks--
    50  	if gp.m.locks < 0 {
    51  		throw("lock count")
    52  	}
    53  	l.key = mutex_unlocked
    54  }
    55  
    56  // One-time notifications.
    57  func noteclear(n *note) {
    58  	n.key = 0
    59  }
    60  
    61  func notewakeup(n *note) {
    62  	if n.key != 0 {
    63  		print("notewakeup - double wakeup (", n.key, ")\n")
    64  		throw("notewakeup - double wakeup")
    65  	}
    66  	n.key = 1
    67  }
    68  
    69  func notesleep(n *note) {
    70  	throw("notesleep not supported by wasi")
    71  }
    72  
    73  func notetsleep(n *note, ns int64) bool {
    74  	throw("notetsleep not supported by wasi")
    75  	return false
    76  }
    77  
    78  // same as runtimeĀ·notetsleep, but called on user g (not g0)
    79  func notetsleepg(n *note, ns int64) bool {
    80  	gp := getg()
    81  	if gp == gp.m.g0 {
    82  		throw("notetsleepg on g0")
    83  	}
    84  
    85  	deadline := nanotime() + ns
    86  	for {
    87  		if n.key != 0 {
    88  			return true
    89  		}
    90  		if sched_yield() != 0 {
    91  			throw("sched_yield failed")
    92  		}
    93  		Gosched()
    94  		if ns >= 0 && nanotime() >= deadline {
    95  			return false
    96  		}
    97  	}
    98  }
    99  
   100  func beforeIdle(int64, int64) (*g, bool) {
   101  	return nil, false
   102  }
   103  
   104  func checkTimeouts() {}
   105  
   106  //go:wasmimport wasi_snapshot_preview1 sched_yield
   107  func sched_yield() errno