|  | // Copyright 2011 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package runtime | 
|  |  | 
|  | import "unsafe" | 
|  |  | 
|  | type mOS struct { | 
|  | waitsema uintptr // semaphore for parking on locks | 
|  | } | 
|  |  | 
|  | func getProcID() uint64 { | 
|  | return uint64(gettid()) | 
|  | } | 
|  |  | 
|  | //extern malloc | 
|  | func libc_malloc(uintptr) unsafe.Pointer | 
|  |  | 
|  | //go:noescape | 
|  | //extern sem_init | 
|  | func sem_init(sem *semt, pshared int32, value uint32) int32 | 
|  |  | 
|  | //go:noescape | 
|  | //extern sem_wait | 
|  | func sem_wait(sem *semt) int32 | 
|  |  | 
|  | //go:noescape | 
|  | //extern sem_post | 
|  | func sem_post(sem *semt) int32 | 
|  |  | 
|  | //go:noescape | 
|  | //extern sem_reltimedwait_np | 
|  | func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 | 
|  |  | 
|  | //go:nosplit | 
|  | func semacreate(mp *m) { | 
|  | if mp.waitsema != 0 { | 
|  | return | 
|  | } | 
|  |  | 
|  | var sem *semt | 
|  |  | 
|  | // Call libc's malloc rather than malloc. This will | 
|  | // allocate space on the C heap. We can't call malloc | 
|  | // here because it could cause a deadlock. | 
|  | sem = (*semt)(libc_malloc(unsafe.Sizeof(*sem))) | 
|  | if sem_init(sem, 0, 0) != 0 { | 
|  | throw("sem_init") | 
|  | } | 
|  | mp.waitsema = uintptr(unsafe.Pointer(sem)) | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func semasleep(ns int64) int32 { | 
|  | _m_ := getg().m | 
|  | if ns >= 0 { | 
|  | var ts timespec | 
|  | ts.setNsec(ns) | 
|  |  | 
|  | if sem_reltimedwait_np((*semt)(unsafe.Pointer(_m_.waitsema)), &ts) != 0 { | 
|  | err := errno() | 
|  | if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR { | 
|  | return -1 | 
|  | } | 
|  | throw("sem_reltimedwait_np") | 
|  | } | 
|  | return 0 | 
|  | } | 
|  | for { | 
|  | r1 := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema))) | 
|  | if r1 == 0 { | 
|  | break | 
|  | } | 
|  | if errno() == _EINTR { | 
|  | continue | 
|  | } | 
|  | throw("sem_wait") | 
|  | } | 
|  | return 0 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func semawakeup(mp *m) { | 
|  | if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 { | 
|  | throw("sem_post") | 
|  | } | 
|  | } |