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