github.com/lzhfromustc/gofuzz@v0.0.0-20211116160056-151b3108bbd1/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  }