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