|  | // Copyright 2019 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. | 
|  |  | 
|  | //go:build faketime && !windows | 
|  |  | 
|  | // Faketime isn't currently supported on Windows. This would require | 
|  | // modifying syscall.Write to call syscall.faketimeWrite, | 
|  | // translating the Stdout and Stderr handles into FDs 1 and 2. | 
|  | // (See CL 192739 PS 3.) | 
|  |  | 
|  | package runtime | 
|  |  | 
|  | import "unsafe" | 
|  |  | 
|  | // faketime is the simulated time in nanoseconds since 1970 for the | 
|  | // playground. | 
|  | var faketime int64 = 1257894000000000000 | 
|  |  | 
|  | var faketimeState struct { | 
|  | lock mutex | 
|  |  | 
|  | // lastfaketime is the last faketime value written to fd 1 or 2. | 
|  | lastfaketime int64 | 
|  |  | 
|  | // lastfd is the fd to which lastfaketime was written. | 
|  | // | 
|  | // Subsequent writes to the same fd may use the same | 
|  | // timestamp, but the timestamp must increase if the fd | 
|  | // changes. | 
|  | lastfd uintptr | 
|  | } | 
|  |  | 
|  | //go:linkname nanotime | 
|  | //go:nosplit | 
|  | func nanotime() int64 { | 
|  | return faketime | 
|  | } | 
|  |  | 
|  | //go:linkname time_now time.now | 
|  | func time_now() (sec int64, nsec int32, mono int64) { | 
|  | return faketime / 1e9, int32(faketime % 1e9), faketime | 
|  | } | 
|  |  | 
|  | // write is like the Unix write system call. | 
|  | // We have to avoid write barriers to avoid potential deadlock | 
|  | // on write calls. | 
|  | // | 
|  | //go:nowritebarrierrec | 
|  | func write(fd uintptr, p unsafe.Pointer, n int32) int32 { | 
|  | if !(fd == 1 || fd == 2) { | 
|  | // Do an ordinary write. | 
|  | return write1(fd, p, n) | 
|  | } | 
|  |  | 
|  | // Write with the playback header. | 
|  |  | 
|  | // First, lock to avoid interleaving writes. | 
|  | lock(&faketimeState.lock) | 
|  |  | 
|  | // If the current fd doesn't match the fd of the previous write, | 
|  | // ensure that the timestamp is strictly greater. That way, we can | 
|  | // recover the original order even if we read the fds separately. | 
|  | t := faketimeState.lastfaketime | 
|  | if fd != faketimeState.lastfd { | 
|  | t++ | 
|  | faketimeState.lastfd = fd | 
|  | } | 
|  | if faketime > t { | 
|  | t = faketime | 
|  | } | 
|  | faketimeState.lastfaketime = t | 
|  |  | 
|  | // Playback header: 0 0 P B <8-byte time> <4-byte data length> (big endian) | 
|  | var buf [4 + 8 + 4]byte | 
|  | buf[2] = 'P' | 
|  | buf[3] = 'B' | 
|  | tu := uint64(t) | 
|  | buf[4] = byte(tu >> (7 * 8)) | 
|  | buf[5] = byte(tu >> (6 * 8)) | 
|  | buf[6] = byte(tu >> (5 * 8)) | 
|  | buf[7] = byte(tu >> (4 * 8)) | 
|  | buf[8] = byte(tu >> (3 * 8)) | 
|  | buf[9] = byte(tu >> (2 * 8)) | 
|  | buf[10] = byte(tu >> (1 * 8)) | 
|  | buf[11] = byte(tu >> (0 * 8)) | 
|  | nu := uint32(n) | 
|  | buf[12] = byte(nu >> (3 * 8)) | 
|  | buf[13] = byte(nu >> (2 * 8)) | 
|  | buf[14] = byte(nu >> (1 * 8)) | 
|  | buf[15] = byte(nu >> (0 * 8)) | 
|  | write1(fd, unsafe.Pointer(&buf[0]), int32(len(buf))) | 
|  |  | 
|  | // Write actual data. | 
|  | res := write1(fd, p, n) | 
|  |  | 
|  | unlock(&faketimeState.lock) | 
|  | return res | 
|  | } |