Accidentally failed to commit these earlier, as part of:
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 11 Oct 2016 00:08:35 +0000 (00:08 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 11 Oct 2016 00:08:35 +0000 (00:08 +0000)
    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

libgo/go/runtime/write_err.go [new file with mode: 0644]
libgo/go/runtime/write_err_android.go [new file with mode: 0644]
libgo/runtime/go-print.c [deleted file]

diff --git a/libgo/go/runtime/write_err.go b/libgo/go/runtime/write_err.go
new file mode 100644 (file)
index 0000000..6b1467b
--- /dev/null
@@ -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 (file)
index 0000000..4411a14
--- /dev/null
@@ -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 (file)
index 4c520de..0000000
+++ /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);
-}