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

View as plain text