1// Copyright 2018 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 5// +build aix 6 7package runtime 8 9import ( 10 "unsafe" 11) 12 13//extern sysconf 14func sysconf(int32) _C_long 15 16type mOS struct { 17 waitsema uintptr // semaphore for parking on locks 18} 19 20func getProcID() uint64 { 21 return uint64(gettid()) 22} 23 24//extern malloc 25func libc_malloc(uintptr) unsafe.Pointer 26 27//go:noescape 28//extern sem_init 29func sem_init(sem *semt, pshared int32, value uint32) int32 30 31//go:noescape 32//extern sem_wait 33func sem_wait(sem *semt) int32 34 35//go:noescape 36//extern sem_post 37func sem_post(sem *semt) int32 38 39//go:noescape 40//extern sem_timedwait 41func sem_timedwait(sem *semt, timeout *timespec) int32 42 43//go:noescape 44//extern clock_gettime 45func clock_gettime(clock_id int64, timeout *timespec) int32 46 47//go:nosplit 48func semacreate(mp *m) { 49 if mp.waitsema != 0 { 50 return 51 } 52 53 var sem *semt 54 55 // Call libc's malloc rather than malloc. This will 56 // allocate space on the C heap. We can't call malloc 57 // here because it could cause a deadlock. 58 sem = (*semt)(libc_malloc(unsafe.Sizeof(*sem))) 59 if sem_init(sem, 0, 0) != 0 { 60 throw("sem_init") 61 } 62 mp.waitsema = uintptr(unsafe.Pointer(sem)) 63} 64 65//go:nosplit 66func semasleep(ns int64) int32 { 67 _m_ := getg().m 68 if ns >= 0 { 69 var ts timespec 70 71 if clock_gettime(_CLOCK_REALTIME, &ts) != 0 { 72 throw("clock_gettime") 73 } 74 75 sec := int64(ts.tv_sec) + ns/1e9 76 nsec := int64(ts.tv_nsec) + ns%1e9 77 if nsec >= 1e9 { 78 sec++ 79 nsec -= 1e9 80 } 81 if sec != int64(timespec_sec_t(sec)) { 82 // Handle overflows (timespec_sec_t is 32-bit in 32-bit applications) 83 sec = 1<<31 - 1 84 } 85 ts.tv_sec = timespec_sec_t(sec) 86 ts.tv_nsec = timespec_nsec_t(nsec) 87 88 if sem_timedwait((*semt)(unsafe.Pointer(_m_.waitsema)), &ts) != 0 { 89 err := errno() 90 if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR { 91 return -1 92 } 93 println("sem_timedwait err ", err, " ts.tv_sec ", ts.tv_sec, " ts.tv_nsec ", ts.tv_nsec, " ns ", ns, " id ", _m_.id) 94 throw("sem_timedwait") 95 } 96 return 0 97 } 98 for { 99 r1 := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema))) 100 if r1 == 0 { 101 break 102 } 103 if errno() == _EINTR { 104 continue 105 } 106 throw("sem_wait") 107 } 108 return 0 109} 110 111//go:nosplit 112func semawakeup(mp *m) { 113 if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 { 114 throw("sem_post") 115 } 116} 117 118func osinit() { 119 ncpu = int32(sysconf(__SC_NPROCESSORS_ONLN)) 120 physPageSize = uintptr(sysconf(__SC_PAGE_SIZE)) 121} 122 123const ( 124 _CLOCK_REALTIME = 9 125 _CLOCK_MONOTONIC = 10 126) 127