Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/vdso_freebsd.go

Documentation: runtime

     1  // Copyright 2018 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 freebsd
     6  // +build freebsd
     7  
     8  package runtime
     9  
    10  import (
    11  	"runtime/internal/atomic"
    12  	"unsafe"
    13  )
    14  
    15  const _VDSO_TH_NUM = 4 // defined in <sys/vdso.h> #ifdef _KERNEL
    16  
    17  var timekeepSharedPage *vdsoTimekeep
    18  
    19  //go:nosplit
    20  func (bt *bintime) Add(bt2 *bintime) {
    21  	u := bt.frac
    22  	bt.frac += bt2.frac
    23  	if u > bt.frac {
    24  		bt.sec++
    25  	}
    26  	bt.sec += bt2.sec
    27  }
    28  
    29  //go:nosplit
    30  func (bt *bintime) AddX(x uint64) {
    31  	u := bt.frac
    32  	bt.frac += x
    33  	if u > bt.frac {
    34  		bt.sec++
    35  	}
    36  }
    37  
    38  var (
    39  	// binuptimeDummy is used in binuptime as the address of an atomic.Load, to simulate
    40  	// an atomic_thread_fence_acq() call which behaves as an instruction reordering and
    41  	// memory barrier.
    42  	binuptimeDummy uint32
    43  
    44  	zeroBintime bintime
    45  )
    46  
    47  // based on /usr/src/lib/libc/sys/__vdso_gettimeofday.c
    48  //
    49  //go:nosplit
    50  func binuptime(abs bool) (bt bintime) {
    51  	timehands := (*[_VDSO_TH_NUM]vdsoTimehands)(add(unsafe.Pointer(timekeepSharedPage), vdsoTimekeepSize))
    52  	for {
    53  		if timekeepSharedPage.enabled == 0 {
    54  			return zeroBintime
    55  		}
    56  
    57  		curr := atomic.Load(&timekeepSharedPage.current) // atomic_load_acq_32
    58  		th := &timehands[curr]
    59  		gen := atomic.Load(&th.gen) // atomic_load_acq_32
    60  		bt = th.offset
    61  
    62  		if tc, ok := th.getTimecounter(); !ok {
    63  			return zeroBintime
    64  		} else {
    65  			delta := (tc - th.offset_count) & th.counter_mask
    66  			bt.AddX(th.scale * uint64(delta))
    67  		}
    68  		if abs {
    69  			bt.Add(&th.boottime)
    70  		}
    71  
    72  		atomic.Load(&binuptimeDummy) // atomic_thread_fence_acq()
    73  		if curr == timekeepSharedPage.current && gen != 0 && gen == th.gen {
    74  			break
    75  		}
    76  	}
    77  	return bt
    78  }
    79  
    80  //go:nosplit
    81  func vdsoClockGettime(clockID int32) bintime {
    82  	if timekeepSharedPage == nil || timekeepSharedPage.ver != _VDSO_TK_VER_CURR {
    83  		return zeroBintime
    84  	}
    85  	abs := false
    86  	switch clockID {
    87  	case _CLOCK_MONOTONIC:
    88  		/* ok */
    89  	case _CLOCK_REALTIME:
    90  		abs = true
    91  	default:
    92  		return zeroBintime
    93  	}
    94  	return binuptime(abs)
    95  }
    96  
    97  func fallback_nanotime() int64
    98  func fallback_walltime() (sec int64, nsec int32)
    99  
   100  //go:nosplit
   101  func nanotime1() int64 {
   102  	bt := vdsoClockGettime(_CLOCK_MONOTONIC)
   103  	if bt == zeroBintime {
   104  		return fallback_nanotime()
   105  	}
   106  	return int64((1e9 * uint64(bt.sec)) + ((1e9 * uint64(bt.frac>>32)) >> 32))
   107  }
   108  
   109  func walltime() (sec int64, nsec int32) {
   110  	bt := vdsoClockGettime(_CLOCK_REALTIME)
   111  	if bt == zeroBintime {
   112  		return fallback_walltime()
   113  	}
   114  	return int64(bt.sec), int32((1e9 * uint64(bt.frac>>32)) >> 32)
   115  }
   116  

View as plain text