1// Copyright 2011 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
5package runtime
6
7import "unsafe"
8
9type mOS struct {
10	waitsema uintptr // semaphore for parking on locks
11}
12
13func getProcID() uint64 {
14	return uint64(gettid())
15}
16
17//extern malloc
18func libc_malloc(uintptr) unsafe.Pointer
19
20//go:noescape
21//extern sem_init
22func sem_init(sem *semt, pshared int32, value uint32) int32
23
24//go:noescape
25//extern sem_wait
26func sem_wait(sem *semt) int32
27
28//go:noescape
29//extern sem_post
30func sem_post(sem *semt) int32
31
32//go:noescape
33//extern sem_reltimedwait_np
34func sem_reltimedwait_np(sem *semt, timeout *timespec) int32
35
36//go:nosplit
37func semacreate(mp *m) {
38	if mp.waitsema != 0 {
39		return
40	}
41
42	var sem *semt
43
44	// Call libc's malloc rather than malloc. This will
45	// allocate space on the C heap. We can't call malloc
46	// here because it could cause a deadlock.
47	sem = (*semt)(libc_malloc(unsafe.Sizeof(*sem)))
48	if sem_init(sem, 0, 0) != 0 {
49		throw("sem_init")
50	}
51	mp.waitsema = uintptr(unsafe.Pointer(sem))
52}
53
54//go:nosplit
55func semasleep(ns int64) int32 {
56	_m_ := getg().m
57	if ns >= 0 {
58		var ts timespec
59		ts.setNsec(ns)
60
61		if sem_reltimedwait_np((*semt)(unsafe.Pointer(_m_.waitsema)), &ts) != 0 {
62			err := errno()
63			if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR {
64				return -1
65			}
66			throw("sem_reltimedwait_np")
67		}
68		return 0
69	}
70	for {
71		r1 := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema)))
72		if r1 == 0 {
73			break
74		}
75		if errno() == _EINTR {
76			continue
77		}
78		throw("sem_wait")
79	}
80	return 0
81}
82
83//go:nosplit
84func semawakeup(mp *m) {
85	if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
86		throw("sem_post")
87	}
88}
89