Source file src/runtime/lock_wasip1.go

     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 mutexContended(l *mutex) bool {
    23  	return false
    24  }
    25  
    26  func lock(l *mutex) {
    27  	lockWithRank(l, getLockRank(l))
    28  }
    29  
    30  func lock2(l *mutex) {
    31  	if l.key == mutex_locked {
    32  		// wasm is single-threaded so we should never
    33  		// observe this.
    34  		throw("self deadlock")
    35  	}
    36  	gp := getg()
    37  	if gp.m.locks < 0 {
    38  		throw("lock count")
    39  	}
    40  	gp.m.locks++
    41  	l.key = mutex_locked
    42  }
    43  
    44  func unlock(l *mutex) {
    45  	unlockWithRank(l)
    46  }
    47  
    48  func unlock2(l *mutex) {
    49  	if l.key == mutex_unlocked {
    50  		throw("unlock of unlocked lock")
    51  	}
    52  	gp := getg()
    53  	gp.m.locks--
    54  	if gp.m.locks < 0 {
    55  		throw("lock count")
    56  	}
    57  	l.key = mutex_unlocked
    58  }
    59  
    60  // One-time notifications.
    61  func noteclear(n *note) {
    62  	n.key = 0
    63  }
    64  
    65  func notewakeup(n *note) {
    66  	if n.key != 0 {
    67  		print("notewakeup - double wakeup (", n.key, ")\n")
    68  		throw("notewakeup - double wakeup")
    69  	}
    70  	n.key = 1
    71  }
    72  
    73  func notesleep(n *note) {
    74  	throw("notesleep not supported by wasi")
    75  }
    76  
    77  func notetsleep(n *note, ns int64) bool {
    78  	throw("notetsleep not supported by wasi")
    79  	return false
    80  }
    81  
    82  // same as runtimeĀ·notetsleep, but called on user g (not g0)
    83  func notetsleepg(n *note, ns int64) bool {
    84  	gp := getg()
    85  	if gp == gp.m.g0 {
    86  		throw("notetsleepg on g0")
    87  	}
    88  
    89  	deadline := nanotime() + ns
    90  	for {
    91  		if n.key != 0 {
    92  			return true
    93  		}
    94  		if sched_yield() != 0 {
    95  			throw("sched_yield failed")
    96  		}
    97  		Gosched()
    98  		if ns >= 0 && nanotime() >= deadline {
    99  			return false
   100  		}
   101  	}
   102  }
   103  
   104  func beforeIdle(int64, int64) (*g, bool) {
   105  	return nil, false
   106  }
   107  
   108  func checkTimeouts() {}
   109  
   110  //go:wasmimport wasi_snapshot_preview1 sched_yield
   111  func sched_yield() errno
   112  

View as plain text