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