...

Source file src/runtime/print.go

Documentation: runtime

		 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  	"runtime/internal/sys"
		10  	"unsafe"
		11  )
		12  
		13  // The compiler knows that a print of a value of this type
		14  // should use printhex instead of printuint (decimal).
		15  type hex uint64
		16  
		17  func bytes(s string) (ret []byte) {
		18  	rp := (*slice)(unsafe.Pointer(&ret))
		19  	sp := stringStructOf(&s)
		20  	rp.array = sp.str
		21  	rp.len = sp.len
		22  	rp.cap = sp.len
		23  	return
		24  }
		25  
		26  var (
		27  	// printBacklog is a circular buffer of messages written with the builtin
		28  	// print* functions, for use in postmortem analysis of core dumps.
		29  	printBacklog			[512]byte
		30  	printBacklogIndex int
		31  )
		32  
		33  // recordForPanic maintains a circular buffer of messages written by the
		34  // runtime leading up to a process crash, allowing the messages to be
		35  // extracted from a core dump.
		36  //
		37  // The text written during a process crash (following "panic" or "fatal
		38  // error") is not saved, since the goroutine stacks will generally be readable
		39  // from the runtime datastructures in the core file.
		40  func recordForPanic(b []byte) {
		41  	printlock()
		42  
		43  	if atomic.Load(&panicking) == 0 {
		44  		// Not actively crashing: maintain circular buffer of print output.
		45  		for i := 0; i < len(b); {
		46  			n := copy(printBacklog[printBacklogIndex:], b[i:])
		47  			i += n
		48  			printBacklogIndex += n
		49  			printBacklogIndex %= len(printBacklog)
		50  		}
		51  	}
		52  
		53  	printunlock()
		54  }
		55  
		56  var debuglock mutex
		57  
		58  // The compiler emits calls to printlock and printunlock around
		59  // the multiple calls that implement a single Go print or println
		60  // statement. Some of the print helpers (printslice, for example)
		61  // call print recursively. There is also the problem of a crash
		62  // happening during the print routines and needing to acquire
		63  // the print lock to print information about the crash.
		64  // For both these reasons, let a thread acquire the printlock 'recursively'.
		65  
		66  func printlock() {
		67  	mp := getg().m
		68  	mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
		69  	mp.printlock++
		70  	if mp.printlock == 1 {
		71  		lock(&debuglock)
		72  	}
		73  	mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
		74  }
		75  
		76  func printunlock() {
		77  	mp := getg().m
		78  	mp.printlock--
		79  	if mp.printlock == 0 {
		80  		unlock(&debuglock)
		81  	}
		82  }
		83  
		84  // write to goroutine-local buffer if diverting output,
		85  // or else standard error.
		86  func gwrite(b []byte) {
		87  	if len(b) == 0 {
		88  		return
		89  	}
		90  	recordForPanic(b)
		91  	gp := getg()
		92  	// Don't use the writebuf if gp.m is dying. We want anything
		93  	// written through gwrite to appear in the terminal rather
		94  	// than be written to in some buffer, if we're in a panicking state.
		95  	// Note that we can't just clear writebuf in the gp.m.dying case
		96  	// because a panic isn't allowed to have any write barriers.
		97  	if gp == nil || gp.writebuf == nil || gp.m.dying > 0 {
		98  		writeErr(b)
		99  		return
	 100  	}
	 101  
	 102  	n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
	 103  	gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
	 104  }
	 105  
	 106  func printsp() {
	 107  	printstring(" ")
	 108  }
	 109  
	 110  func printnl() {
	 111  	printstring("\n")
	 112  }
	 113  
	 114  func printbool(v bool) {
	 115  	if v {
	 116  		printstring("true")
	 117  	} else {
	 118  		printstring("false")
	 119  	}
	 120  }
	 121  
	 122  func printfloat(v float64) {
	 123  	switch {
	 124  	case v != v:
	 125  		printstring("NaN")
	 126  		return
	 127  	case v+v == v && v > 0:
	 128  		printstring("+Inf")
	 129  		return
	 130  	case v+v == v && v < 0:
	 131  		printstring("-Inf")
	 132  		return
	 133  	}
	 134  
	 135  	const n = 7 // digits printed
	 136  	var buf [n + 7]byte
	 137  	buf[0] = '+'
	 138  	e := 0 // exp
	 139  	if v == 0 {
	 140  		if 1/v < 0 {
	 141  			buf[0] = '-'
	 142  		}
	 143  	} else {
	 144  		if v < 0 {
	 145  			v = -v
	 146  			buf[0] = '-'
	 147  		}
	 148  
	 149  		// normalize
	 150  		for v >= 10 {
	 151  			e++
	 152  			v /= 10
	 153  		}
	 154  		for v < 1 {
	 155  			e--
	 156  			v *= 10
	 157  		}
	 158  
	 159  		// round
	 160  		h := 5.0
	 161  		for i := 0; i < n; i++ {
	 162  			h /= 10
	 163  		}
	 164  		v += h
	 165  		if v >= 10 {
	 166  			e++
	 167  			v /= 10
	 168  		}
	 169  	}
	 170  
	 171  	// format +d.dddd+edd
	 172  	for i := 0; i < n; i++ {
	 173  		s := int(v)
	 174  		buf[i+2] = byte(s + '0')
	 175  		v -= float64(s)
	 176  		v *= 10
	 177  	}
	 178  	buf[1] = buf[2]
	 179  	buf[2] = '.'
	 180  
	 181  	buf[n+2] = 'e'
	 182  	buf[n+3] = '+'
	 183  	if e < 0 {
	 184  		e = -e
	 185  		buf[n+3] = '-'
	 186  	}
	 187  
	 188  	buf[n+4] = byte(e/100) + '0'
	 189  	buf[n+5] = byte(e/10)%10 + '0'
	 190  	buf[n+6] = byte(e%10) + '0'
	 191  	gwrite(buf[:])
	 192  }
	 193  
	 194  func printcomplex(c complex128) {
	 195  	print("(", real(c), imag(c), "i)")
	 196  }
	 197  
	 198  func printuint(v uint64) {
	 199  	var buf [100]byte
	 200  	i := len(buf)
	 201  	for i--; i > 0; i-- {
	 202  		buf[i] = byte(v%10 + '0')
	 203  		if v < 10 {
	 204  			break
	 205  		}
	 206  		v /= 10
	 207  	}
	 208  	gwrite(buf[i:])
	 209  }
	 210  
	 211  func printint(v int64) {
	 212  	if v < 0 {
	 213  		printstring("-")
	 214  		v = -v
	 215  	}
	 216  	printuint(uint64(v))
	 217  }
	 218  
	 219  var minhexdigits = 0 // protected by printlock
	 220  
	 221  func printhex(v uint64) {
	 222  	const dig = "0123456789abcdef"
	 223  	var buf [100]byte
	 224  	i := len(buf)
	 225  	for i--; i > 0; i-- {
	 226  		buf[i] = dig[v%16]
	 227  		if v < 16 && len(buf)-i >= minhexdigits {
	 228  			break
	 229  		}
	 230  		v /= 16
	 231  	}
	 232  	i--
	 233  	buf[i] = 'x'
	 234  	i--
	 235  	buf[i] = '0'
	 236  	gwrite(buf[i:])
	 237  }
	 238  
	 239  func printpointer(p unsafe.Pointer) {
	 240  	printhex(uint64(uintptr(p)))
	 241  }
	 242  func printuintptr(p uintptr) {
	 243  	printhex(uint64(p))
	 244  }
	 245  
	 246  func printstring(s string) {
	 247  	gwrite(bytes(s))
	 248  }
	 249  
	 250  func printslice(s []byte) {
	 251  	sp := (*slice)(unsafe.Pointer(&s))
	 252  	print("[", len(s), "/", cap(s), "]")
	 253  	printpointer(sp.array)
	 254  }
	 255  
	 256  func printeface(e eface) {
	 257  	print("(", e._type, ",", e.data, ")")
	 258  }
	 259  
	 260  func printiface(i iface) {
	 261  	print("(", i.tab, ",", i.data, ")")
	 262  }
	 263  
	 264  // hexdumpWords prints a word-oriented hex dump of [p, end).
	 265  //
	 266  // If mark != nil, it will be called with each printed word's address
	 267  // and should return a character mark to appear just before that
	 268  // word's value. It can return 0 to indicate no mark.
	 269  func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
	 270  	printlock()
	 271  	var markbuf [1]byte
	 272  	markbuf[0] = ' '
	 273  	minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2)
	 274  	for i := uintptr(0); p+i < end; i += sys.PtrSize {
	 275  		if i%16 == 0 {
	 276  			if i != 0 {
	 277  				println()
	 278  			}
	 279  			print(hex(p+i), ": ")
	 280  		}
	 281  
	 282  		if mark != nil {
	 283  			markbuf[0] = mark(p + i)
	 284  			if markbuf[0] == 0 {
	 285  				markbuf[0] = ' '
	 286  			}
	 287  		}
	 288  		gwrite(markbuf[:])
	 289  		val := *(*uintptr)(unsafe.Pointer(p + i))
	 290  		print(hex(val))
	 291  		print(" ")
	 292  
	 293  		// Can we symbolize val?
	 294  		fn := findfunc(val)
	 295  		if fn.valid() {
	 296  			print("<", funcname(fn), "+", hex(val-fn.entry), "> ")
	 297  		}
	 298  	}
	 299  	minhexdigits = 0
	 300  	println()
	 301  	printunlock()
	 302  }
	 303  

View as plain text