]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/print.go
all: fix typos in go file comments
[gostls13.git] / src / runtime / print.go
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         "internal/goarch"
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 data structures in the core file.
39 func recordForPanic(b []byte) {
40         printlock()
41
42         if panicking.Load() == 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         // Don't use the writebuf if gp.m is dying. We want anything
92         // written through gwrite to appear in the terminal rather
93         // than be written to in some buffer, if we're in a panicking state.
94         // Note that we can't just clear writebuf in the gp.m.dying case
95         // because a panic isn't allowed to have any write barriers.
96         if gp == nil || gp.writebuf == nil || gp.m.dying > 0 {
97                 writeErr(b)
98                 return
99         }
100
101         n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
102         gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
103 }
104
105 func printsp() {
106         printstring(" ")
107 }
108
109 func printnl() {
110         printstring("\n")
111 }
112
113 func printbool(v bool) {
114         if v {
115                 printstring("true")
116         } else {
117                 printstring("false")
118         }
119 }
120
121 func printfloat(v float64) {
122         switch {
123         case v != v:
124                 printstring("NaN")
125                 return
126         case v+v == v && v > 0:
127                 printstring("+Inf")
128                 return
129         case v+v == v && v < 0:
130                 printstring("-Inf")
131                 return
132         }
133
134         const n = 7 // digits printed
135         var buf [n + 7]byte
136         buf[0] = '+'
137         e := 0 // exp
138         if v == 0 {
139                 if 1/v < 0 {
140                         buf[0] = '-'
141                 }
142         } else {
143                 if v < 0 {
144                         v = -v
145                         buf[0] = '-'
146                 }
147
148                 // normalize
149                 for v >= 10 {
150                         e++
151                         v /= 10
152                 }
153                 for v < 1 {
154                         e--
155                         v *= 10
156                 }
157
158                 // round
159                 h := 5.0
160                 for i := 0; i < n; i++ {
161                         h /= 10
162                 }
163                 v += h
164                 if v >= 10 {
165                         e++
166                         v /= 10
167                 }
168         }
169
170         // format +d.dddd+edd
171         for i := 0; i < n; i++ {
172                 s := int(v)
173                 buf[i+2] = byte(s + '0')
174                 v -= float64(s)
175                 v *= 10
176         }
177         buf[1] = buf[2]
178         buf[2] = '.'
179
180         buf[n+2] = 'e'
181         buf[n+3] = '+'
182         if e < 0 {
183                 e = -e
184                 buf[n+3] = '-'
185         }
186
187         buf[n+4] = byte(e/100) + '0'
188         buf[n+5] = byte(e/10)%10 + '0'
189         buf[n+6] = byte(e%10) + '0'
190         gwrite(buf[:])
191 }
192
193 func printcomplex(c complex128) {
194         print("(", real(c), imag(c), "i)")
195 }
196
197 func printuint(v uint64) {
198         var buf [100]byte
199         i := len(buf)
200         for i--; i > 0; i-- {
201                 buf[i] = byte(v%10 + '0')
202                 if v < 10 {
203                         break
204                 }
205                 v /= 10
206         }
207         gwrite(buf[i:])
208 }
209
210 func printint(v int64) {
211         if v < 0 {
212                 printstring("-")
213                 v = -v
214         }
215         printuint(uint64(v))
216 }
217
218 var minhexdigits = 0 // protected by printlock
219
220 func printhex(v uint64) {
221         const dig = "0123456789abcdef"
222         var buf [100]byte
223         i := len(buf)
224         for i--; i > 0; i-- {
225                 buf[i] = dig[v%16]
226                 if v < 16 && len(buf)-i >= minhexdigits {
227                         break
228                 }
229                 v /= 16
230         }
231         i--
232         buf[i] = 'x'
233         i--
234         buf[i] = '0'
235         gwrite(buf[i:])
236 }
237
238 func printpointer(p unsafe.Pointer) {
239         printhex(uint64(uintptr(p)))
240 }
241 func printuintptr(p uintptr) {
242         printhex(uint64(p))
243 }
244
245 func printstring(s string) {
246         gwrite(bytes(s))
247 }
248
249 func printslice(s []byte) {
250         sp := (*slice)(unsafe.Pointer(&s))
251         print("[", len(s), "/", cap(s), "]")
252         printpointer(sp.array)
253 }
254
255 func printeface(e eface) {
256         print("(", e._type, ",", e.data, ")")
257 }
258
259 func printiface(i iface) {
260         print("(", i.tab, ",", i.data, ")")
261 }
262
263 // hexdumpWords prints a word-oriented hex dump of [p, end).
264 //
265 // If mark != nil, it will be called with each printed word's address
266 // and should return a character mark to appear just before that
267 // word's value. It can return 0 to indicate no mark.
268 func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
269         printlock()
270         var markbuf [1]byte
271         markbuf[0] = ' '
272         minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2)
273         for i := uintptr(0); p+i < end; i += goarch.PtrSize {
274                 if i%16 == 0 {
275                         if i != 0 {
276                                 println()
277                         }
278                         print(hex(p+i), ": ")
279                 }
280
281                 if mark != nil {
282                         markbuf[0] = mark(p + i)
283                         if markbuf[0] == 0 {
284                                 markbuf[0] = ' '
285                         }
286                 }
287                 gwrite(markbuf[:])
288                 val := *(*uintptr)(unsafe.Pointer(p + i))
289                 print(hex(val))
290                 print(" ")
291
292                 // Can we symbolize val?
293                 fn := findfunc(val)
294                 if fn.valid() {
295                         print("<", funcname(fn), "+", hex(val-fn.entry()), "> ")
296                 }
297         }
298         minhexdigits = 0
299         println()
300         printunlock()
301 }