1 // Copyright 2014 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.
8 "runtime/internal/atomic"
19 func lwp_park(ts
int32, rel
int32, abstime
*timespec
, unpark
int32, hint
, unparkhint unsafe
.Pointer
) int32
23 func lwp_unpark(lwp
int32, hint unsafe
.Pointer
) int32
26 func semacreate(mp
*m
) {
30 func semasleep(ns
int64) int32 {
33 // Compute sleep deadline.
38 ts
.set_sec(int64(timediv(ns
, 1000000000, &nsec
)))
44 v
:= atomic
.Load(&_g_
.m
.mos
.waitsemacount
)
46 if atomic
.Cas(&_g_
.m
.mos
.waitsemacount
, v
, v
-1) {
47 return 0 // semaphore acquired
52 // Sleep until unparked by semawakeup or timeout.
53 ret
:= lwp_park(_CLOCK_MONOTONIC
, _TIMER_RELTIME
, tsp
, 0, unsafe
.Pointer(&_g_
.m
.waitsemacount
), nil)
54 if ret
== _ETIMEDOUT
{
56 } else if ret
== _EINTR
&& ns
>= 0 {
57 // Avoid sleeping forever if we keep getting
58 // interrupted (for example by the profiling
59 // timer). It would be if tsp upon return had the
60 // remaining time to sleep, but this is good enough.
63 ts
.set_sec(timediv(ns
, 1000000000, &nsec
))
70 func semawakeup(mp
*m
) {
71 atomic
.Xadd(&mp
.mos
.waitsemacount
, 1)
72 // From NetBSD's _lwp_unpark(2) manual:
73 // "If the target LWP is not currently waiting, it will return
74 // immediately upon the next call to _lwp_park()."
75 ret
:= lwp_unpark(int32(mp
.procid
), unsafe
.Pointer(&mp
.mos
.waitsemacount
))
76 if ret
!= 0 && ret
!= _ESRCH
{
77 // semawakeup can be called on signal stack.
79 print("thrwakeup addr=", &mp
.mos
.waitsemacount
, " sem=", mp
.mos
.waitsemacount
, " ret=", ret
, "\n")