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

View as plain text