github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/src/runtime/print.go (about) 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. 4 5 package runtime 6 7 import ( 8 "runtime/internal/atomic" 9 "unsafe" 10 ) 11 12 // The compiler knows that a print of a value of this type 13 // should use printhex instead of printuint (decimal). 14 type hex uint64 15 16 func bytes(s string) (ret []byte) { 17 rp := (*slice)(unsafe.Pointer(&ret)) 18 sp := stringStructOf(&s) 19 rp.array = sp.str 20 rp.len = sp.len 21 rp.cap = sp.len 22 return 23 } 24 25 var ( 26 // printBacklog is a circular buffer of messages written with the builtin 27 // print* functions, for use in postmortem analysis of core dumps. 28 printBacklog [512]byte 29 printBacklogIndex int 30 ) 31 32 // recordForPanic maintains a circular buffer of messages written by the 33 // runtime leading up to a process crash, allowing the messages to be 34 // extracted from a core dump. 35 // 36 // The text written during a process crash (following "panic" or "fatal 37 // error") is not saved, since the goroutine stacks will generally be readable 38 // from the runtime datastructures in the core file. 39 func recordForPanic(b []byte) { 40 printlock() 41 42 if atomic.Load(&panicking) == 0 { 43 // Not actively crashing: maintain circular buffer of print output. 44 for i := 0; i < len(b); { 45 n := copy(printBacklog[printBacklogIndex:], b[i:]) 46 i += n 47 printBacklogIndex += n 48 printBacklogIndex %= len(printBacklog) 49 } 50 } 51 52 printunlock() 53 } 54 55 var debuglock mutex 56 57 // The compiler emits calls to printlock and printunlock around 58 // the multiple calls that implement a single Go print or println 59 // statement. Some of the print helpers (printslice, for example) 60 // call print recursively. There is also the problem of a crash 61 // happening during the print routines and needing to acquire 62 // the print lock to print information about the crash. 63 // For both these reasons, let a thread acquire the printlock 'recursively'. 64 65 func printlock() { 66 mp := getg().m 67 mp.locks++ // do not reschedule between printlock++ and lock(&debuglock). 68 mp.printlock++ 69 if mp.printlock == 1 { 70 lock(&debuglock) 71 } 72 mp.locks-- // now we know debuglock is held and holding up mp.locks for us. 73 } 74 75 func printunlock() { 76 mp := getg().m 77 mp.printlock-- 78 if mp.printlock == 0 { 79 unlock(&debuglock) 80 } 81 } 82 83 // write to goroutine-local buffer if diverting output, 84 // or else standard error. 85 func gwrite(b []byte) { 86 if len(b) == 0 { 87 return 88 } 89 recordForPanic(b) 90 gp := getg() 91 if gp == nil || gp.writebuf == nil { 92 writeErr(b) 93 return 94 } 95 96 n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b) 97 gp.writebuf = gp.writebuf[:len(gp.writebuf)+n] 98 } 99 100 func printsp() { 101 printstring(" ") 102 } 103 104 func printnl() { 105 printstring("\n") 106 } 107 108 func printbool(v bool) { 109 if v { 110 printstring("true") 111 } else { 112 printstring("false") 113 } 114 } 115 116 func printfloat(v float64) { 117 switch { 118 case v != v: 119 printstring("NaN") 120 return 121 case v+v == v && v > 0: 122 printstring("+Inf") 123 return 124 case v+v == v && v < 0: 125 printstring("-Inf") 126 return 127 } 128 129 const n = 7 // digits printed 130 var buf [n + 7]byte 131 buf[0] = '+' 132 e := 0 // exp 133 if v == 0 { 134 if 1/v < 0 { 135 buf[0] = '-' 136 } 137 } else { 138 if v < 0 { 139 v = -v 140 buf[0] = '-' 141 } 142 143 // normalize 144 for v >= 10 { 145 e++ 146 v /= 10 147 } 148 for v < 1 { 149 e-- 150 v *= 10 151 } 152 153 // round 154 h := 5.0 155 for i := 0; i < n; i++ { 156 h /= 10 157 } 158 v += h 159 if v >= 10 { 160 e++ 161 v /= 10 162 } 163 } 164 165 // format +d.dddd+edd 166 for i := 0; i < n; i++ { 167 s := int(v) 168 buf[i+2] = byte(s + '0') 169 v -= float64(s) 170 v *= 10 171 } 172 buf[1] = buf[2] 173 buf[2] = '.' 174 175 buf[n+2] = 'e' 176 buf[n+3] = '+' 177 if e < 0 { 178 e = -e 179 buf[n+3] = '-' 180 } 181 182 buf[n+4] = byte(e/100) + '0' 183 buf[n+5] = byte(e/10)%10 + '0' 184 buf[n+6] = byte(e%10) + '0' 185 gwrite(buf[:]) 186 } 187 188 func printcomplex(c complex128) { 189 print("(", real(c), imag(c), "i)") 190 } 191 192 func printuint(v uint64) { 193 var buf [100]byte 194 i := len(buf) 195 for i--; i > 0; i-- { 196 buf[i] = byte(v%10 + '0') 197 if v < 10 { 198 break 199 } 200 v /= 10 201 } 202 gwrite(buf[i:]) 203 } 204 205 func printint(v int64) { 206 if v < 0 { 207 printstring("-") 208 v = -v 209 } 210 printuint(uint64(v)) 211 } 212 213 func printhex(v uint64) { 214 const dig = "0123456789abcdef" 215 var buf [100]byte 216 i := len(buf) 217 for i--; i > 0; i-- { 218 buf[i] = dig[v%16] 219 if v < 16 { 220 break 221 } 222 v /= 16 223 } 224 i-- 225 buf[i] = 'x' 226 i-- 227 buf[i] = '0' 228 gwrite(buf[i:]) 229 } 230 231 func printpointer(p unsafe.Pointer) { 232 printhex(uint64(uintptr(p))) 233 } 234 235 func printstring(s string) { 236 gwrite(bytes(s)) 237 } 238 239 func printslice(s []byte) { 240 sp := (*slice)(unsafe.Pointer(&s)) 241 print("[", len(s), "/", cap(s), "]") 242 printpointer(sp.array) 243 } 244 245 func printeface(e eface) { 246 print("(", e._type, ",", e.data, ")") 247 } 248 249 func printiface(i iface) { 250 print("(", i.tab, ",", i.data, ")") 251 }