aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-10-11 00:08:35 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-10-11 00:08:35 +0000
commitabe08b7d909d27884e9f5f2cb879739e2c909106 (patch)
tree4bf60096697ceb0808430d2f207d7b3220b44460 /libgo
parent5b69c5e55df08ca91989f746ed2b459e0658d6dd (diff)
downloadgcc-abe08b7d909d27884e9f5f2cb879739e2c909106.zip
gcc-abe08b7d909d27884e9f5f2cb879739e2c909106.tar.gz
gcc-abe08b7d909d27884e9f5f2cb879739e2c909106.tar.bz2
Accidentally failed to commit these earlier, as part of:
Update the compiler to use the new names. Add calls to printlock and printunlock around print statements. Move expression evaluation before the call to printlock. Update g's writebuf field to a slice, and adjust C code accordingly. Reviewed-on: https://go-review.googlesource.com/30717 From-SVN: r240958
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/write_err.go13
-rw-r--r--libgo/go/runtime/write_err_android.go160
-rw-r--r--libgo/runtime/go-print.c36
3 files changed, 173 insertions, 36 deletions
diff --git a/libgo/go/runtime/write_err.go b/libgo/go/runtime/write_err.go
new file mode 100644
index 0000000..6b1467b
--- /dev/null
+++ b/libgo/go/runtime/write_err.go
@@ -0,0 +1,13 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !android
+
+package runtime
+
+import "unsafe"
+
+func writeErr(b []byte) {
+ write(2, unsafe.Pointer(&b[0]), int32(len(b)))
+}
diff --git a/libgo/go/runtime/write_err_android.go b/libgo/go/runtime/write_err_android.go
new file mode 100644
index 0000000..4411a14
--- /dev/null
+++ b/libgo/go/runtime/write_err_android.go
@@ -0,0 +1,160 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+var (
+ writeHeader = []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0}
+ writePath = []byte("/dev/log/main\x00")
+ writeLogd = []byte("/dev/socket/logdw\x00")
+
+ // guarded by printlock/printunlock.
+ writeFD uintptr
+ writeBuf [1024]byte
+ writePos int
+)
+
+// Prior to Android-L, logging was done through writes to /dev/log files implemented
+// in kernel ring buffers. In Android-L, those /dev/log files are no longer
+// accessible and logging is done through a centralized user-mode logger, logd.
+//
+// https://android.googlesource.com/platform/system/core/+/master/liblog/logd_write.c
+type loggerType int32
+
+const (
+ unknown loggerType = iota
+ legacy
+ logd
+ // TODO(hakim): logging for emulator?
+)
+
+var logger loggerType
+
+func writeErr(b []byte) {
+ if logger == unknown {
+ // Use logd if /dev/socket/logdw is available.
+ if v := uintptr(access(&writeLogd[0], 0x02 /* W_OK */)); v == 0 {
+ logger = logd
+ initLogd()
+ } else {
+ logger = legacy
+ initLegacy()
+ }
+ }
+
+ // Write to stderr for command-line programs.
+ write(2, unsafe.Pointer(&b[0]), int32(len(b)))
+
+ // Log format: "<header>\x00<message m bytes>\x00"
+ //
+ // <header>
+ // In legacy mode: "<priority 1 byte><tag n bytes>".
+ // In logd mode: "<android_log_header_t 11 bytes><priority 1 byte><tag n bytes>"
+ //
+ // The entire log needs to be delivered in a single syscall (the NDK
+ // does this with writev). Each log is its own line, so we need to
+ // buffer writes until we see a newline.
+ var hlen int
+ switch logger {
+ case logd:
+ hlen = writeLogdHeader()
+ case legacy:
+ hlen = len(writeHeader)
+ }
+
+ dst := writeBuf[hlen:]
+ for _, v := range b {
+ if v == 0 { // android logging won't print a zero byte
+ v = '0'
+ }
+ dst[writePos] = v
+ writePos++
+ if v == '\n' || writePos == len(dst)-1 {
+ dst[writePos] = 0
+ write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos))
+ memclrBytes(dst)
+ writePos = 0
+ }
+ }
+}
+
+func initLegacy() {
+ // In legacy mode, logs are written to /dev/log/main
+ writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0))
+ if writeFD == 0 {
+ // It is hard to do anything here. Write to stderr just
+ // in case user has root on device and has run
+ // adb shell setprop log.redirect-stdio true
+ msg := []byte("runtime: cannot open /dev/log/main\x00")
+ write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+ exit(2)
+ }
+
+ // Prepopulate the invariant header part.
+ copy(writeBuf[:len(writeHeader)], writeHeader)
+}
+
+// used in initLogdWrite but defined here to avoid heap allocation.
+var logdAddr sockaddr_un
+
+func initLogd() {
+ // In logd mode, logs are sent to the logd via a unix domain socket.
+ logdAddr.family = _AF_UNIX
+ copy(logdAddr.path[:], writeLogd)
+
+ // We are not using non-blocking I/O because writes taking this path
+ // are most likely triggered by panic, we cannot think of the advantage of
+ // non-blocking I/O for panic but see disadvantage (dropping panic message),
+ // and blocking I/O simplifies the code a lot.
+ fd := socket(_AF_UNIX, _SOCK_DGRAM|_O_CLOEXEC, 0)
+ if fd < 0 {
+ msg := []byte("runtime: cannot create a socket for logging\x00")
+ write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+ exit(2)
+ }
+
+ errno := connect(fd, unsafe.Pointer(&logdAddr), int32(unsafe.Sizeof(logdAddr)))
+ if errno < 0 {
+ msg := []byte("runtime: cannot connect to /dev/socket/logdw\x00")
+ write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+ // TODO(hakim): or should we just close fd and hope for better luck next time?
+ exit(2)
+ }
+ writeFD = uintptr(fd)
+
+ // Prepopulate invariant part of the header.
+ // The first 11 bytes will be populated later in writeLogdHeader.
+ copy(writeBuf[11:11+len(writeHeader)], writeHeader)
+}
+
+// writeLogdHeader populates the header and returns the length of the payload.
+func writeLogdHeader() int {
+ hdr := writeBuf[:11]
+
+ // The first 11 bytes of the header corresponds to android_log_header_t
+ // as defined in system/core/include/private/android_logger.h
+ // hdr[0] log type id (unsigned char), defined in <log/log.h>
+ // hdr[1:2] tid (uint16_t)
+ // hdr[3:11] log_time defined in <log/log_read.h>
+ // hdr[3:7] sec unsigned uint32, little endian.
+ // hdr[7:11] nsec unsigned uint32, little endian.
+ hdr[0] = 0 // LOG_ID_MAIN
+ sec, nsec := time_now()
+ packUint32(hdr[3:7], uint32(sec))
+ packUint32(hdr[7:11], uint32(nsec))
+
+ // TODO(hakim): hdr[1:2] = gettid?
+
+ return 11 + len(writeHeader)
+}
+
+func packUint32(b []byte, v uint32) {
+ // little-endian.
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
diff --git a/libgo/runtime/go-print.c b/libgo/runtime/go-print.c
deleted file mode 100644
index 4c520de..0000000
--- a/libgo/runtime/go-print.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* go-print.c -- support for the go print statement.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "runtime.h"
-#include "array.h"
-#include "go-panic.h"
-#include "interface.h"
-
-/* This implements the various little functions which are called by
- the predeclared functions print/println/panic/panicln. */
-
-void
-__go_print_empty_interface (struct __go_empty_interface e)
-{
- runtime_printf ("(%p,%p)", e.__type_descriptor, e.__object);
-}
-
-void
-__go_print_interface (struct __go_interface i)
-{
- runtime_printf ("(%p,%p)", i.__methods, i.__object);
-}
-
-void
-__go_print_slice (struct __go_open_array val)
-{
- runtime_printf ("[%d/%d]", val.__count, val.__capacity);
- runtime_printpointer (val.__values);
-}