1// Copyright 2019 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//go:build faketime && !windows 6 7// Faketime isn't currently supported on Windows. This would require 8// modifying syscall.Write to call syscall.faketimeWrite, 9// translating the Stdout and Stderr handles into FDs 1 and 2. 10// (See CL 192739 PS 3.) 11 12package runtime 13 14import "unsafe" 15 16// faketime is the simulated time in nanoseconds since 1970 for the 17// playground. 18var faketime int64 = 1257894000000000000 19 20var faketimeState struct { 21 lock mutex 22 23 // lastfaketime is the last faketime value written to fd 1 or 2. 24 lastfaketime int64 25 26 // lastfd is the fd to which lastfaketime was written. 27 // 28 // Subsequent writes to the same fd may use the same 29 // timestamp, but the timestamp must increase if the fd 30 // changes. 31 lastfd uintptr 32} 33 34//go:linkname nanotime 35//go:nosplit 36func nanotime() int64 { 37 return faketime 38} 39 40//go:linkname time_now time.now 41func time_now() (sec int64, nsec int32, mono int64) { 42 return faketime / 1e9, int32(faketime % 1e9), faketime 43} 44 45// write is like the Unix write system call. 46// We have to avoid write barriers to avoid potential deadlock 47// on write calls. 48// 49//go:nowritebarrierrec 50func write(fd uintptr, p unsafe.Pointer, n int32) int32 { 51 if !(fd == 1 || fd == 2) { 52 // Do an ordinary write. 53 return write1(fd, p, n) 54 } 55 56 // Write with the playback header. 57 58 // First, lock to avoid interleaving writes. 59 lock(&faketimeState.lock) 60 61 // If the current fd doesn't match the fd of the previous write, 62 // ensure that the timestamp is strictly greater. That way, we can 63 // recover the original order even if we read the fds separately. 64 t := faketimeState.lastfaketime 65 if fd != faketimeState.lastfd { 66 t++ 67 faketimeState.lastfd = fd 68 } 69 if faketime > t { 70 t = faketime 71 } 72 faketimeState.lastfaketime = t 73 74 // Playback header: 0 0 P B <8-byte time> <4-byte data length> (big endian) 75 var buf [4 + 8 + 4]byte 76 buf[2] = 'P' 77 buf[3] = 'B' 78 tu := uint64(t) 79 buf[4] = byte(tu >> (7 * 8)) 80 buf[5] = byte(tu >> (6 * 8)) 81 buf[6] = byte(tu >> (5 * 8)) 82 buf[7] = byte(tu >> (4 * 8)) 83 buf[8] = byte(tu >> (3 * 8)) 84 buf[9] = byte(tu >> (2 * 8)) 85 buf[10] = byte(tu >> (1 * 8)) 86 buf[11] = byte(tu >> (0 * 8)) 87 nu := uint32(n) 88 buf[12] = byte(nu >> (3 * 8)) 89 buf[13] = byte(nu >> (2 * 8)) 90 buf[14] = byte(nu >> (1 * 8)) 91 buf[15] = byte(nu >> (0 * 8)) 92 write1(fd, unsafe.Pointer(&buf[0]), int32(len(buf))) 93 94 // Write actual data. 95 res := write1(fd, p, n) 96 97 unlock(&faketimeState.lock) 98 return res 99} 100