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