runtime: scan register backing store on ia64
[official-gcc.git] / libgo / go / runtime / os_linux.go
blob816327e70b837a754dfefd2aca44ca8329ddd823
1 // Copyright 2009 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.
5 package runtime
7 import (
8 "runtime/internal/sys"
9 "unsafe"
12 type mOS struct {
13 unused byte
16 func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 {
17 return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3)))
20 // Linux futex.
22 // futexsleep(uint32 *addr, uint32 val)
23 // futexwakeup(uint32 *addr)
25 // Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
26 // Futexwakeup wakes up threads sleeping on addr.
27 // Futexsleep is allowed to wake up spuriously.
29 const (
30 _FUTEX_WAIT = 0
31 _FUTEX_WAKE = 1
34 // Atomically,
35 // if(*addr == val) sleep
36 // Might be woken up spuriously; that's allowed.
37 // Don't sleep longer than ns; ns < 0 means forever.
38 //go:nosplit
39 func futexsleep(addr *uint32, val uint32, ns int64) {
40 var ts timespec
42 // Some Linux kernels have a bug where futex of
43 // FUTEX_WAIT returns an internal error code
44 // as an errno. Libpthread ignores the return value
45 // here, and so can we: as it says a few lines up,
46 // spurious wakeups are allowed.
47 if ns < 0 {
48 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
49 return
52 // It's difficult to live within the no-split stack limits here.
53 // On ARM and 386, a 64-bit divide invokes a general software routine
54 // that needs more stack than we can afford. So we use timediv instead.
55 // But on real 64-bit systems, where words are larger but the stack limit
56 // is not, even timediv is too heavy, and we really need to use just an
57 // ordinary machine instruction.
58 if sys.PtrSize == 8 {
59 ts.set_sec(ns / 1000000000)
60 ts.set_nsec(int32(ns % 1000000000))
61 } else {
62 ts.tv_nsec = 0
63 ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
65 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
68 // If any procs are sleeping on addr, wake up at most cnt.
69 //go:nosplit
70 func futexwakeup(addr *uint32, cnt uint32) {
71 ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
72 if ret >= 0 {
73 return
76 // I don't know that futex wakeup can return
77 // EAGAIN or EINTR, but if it does, it would be
78 // safe to loop and call futex again.
79 systemstack(func() {
80 print("futexwakeup addr=", addr, " returned ", ret, "\n")
83 *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
86 const (
87 _AT_NULL = 0 // End of vector
88 _AT_PAGESZ = 6 // System physical page size
89 _AT_HWCAP = 16 // hardware capability bit vector
90 _AT_RANDOM = 25 // introduced in 2.6.29
91 _AT_HWCAP2 = 26 // hardware capability bit vector 2
94 var procAuxv = []byte("/proc/self/auxv\x00")
96 func sysargs(argc int32, argv **byte) {
97 n := argc + 1
99 // skip over argv, envp to get to auxv
100 for argv_index(argv, n) != nil {
104 // skip NULL separator
107 // now argv+n is auxv
108 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
109 if sysauxv(auxv[:]) != 0 {
110 return
112 // In some situations we don't get a loader-provided
113 // auxv, such as when loaded as a library on Android.
114 // Fall back to /proc/self/auxv.
115 fd := open(&procAuxv[0], 0 /* O_RDONLY */, 0)
116 if fd < 0 {
117 // On Android, /proc/self/auxv might be unreadable (issue 9229), so we fallback to
118 // try using mincore to detect the physical page size.
119 // mincore should return EINVAL when address is not a multiple of system page size.
120 const size = 256 << 10 // size of memory region to allocate
121 p, err := mmap(nil, size, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
122 if err != 0 {
123 return
125 var n uintptr
126 for n = 4 << 10; n < size; n <<= 1 {
127 err := mincore(unsafe.Pointer(uintptr(p)+n), 1, &addrspace_vec[0])
128 if err == 0 {
129 physPageSize = n
130 break
133 if physPageSize == 0 {
134 physPageSize = size
136 munmap(p, size)
137 return
139 var buf [128]uintptr
140 n = read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
141 closefd(fd)
142 if n < 0 {
143 return
145 // Make sure buf is terminated, even if we didn't read
146 // the whole file.
147 buf[len(buf)-2] = _AT_NULL
148 sysauxv(buf[:])
151 func sysauxv(auxv []uintptr) int {
152 var i int
153 for ; auxv[i] != _AT_NULL; i += 2 {
154 tag, val := auxv[i], auxv[i+1]
155 switch tag {
156 case _AT_RANDOM:
157 // The kernel provides a pointer to 16-bytes
158 // worth of random data.
159 startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:]
161 case _AT_PAGESZ:
162 physPageSize = val
165 // Commented out for gccgo for now.
166 // archauxv(tag, val)
168 return i / 2