github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/rt/gcwb.go (about)

     1  /*
     2   * Copyright 2021 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package rt
    18  
    19  import (
    20  	"os"
    21  	"sync/atomic"
    22  	"unsafe"
    23  
    24  	"golang.org/x/arch/x86/x86asm"
    25  )
    26  
    27  const (
    28  	_MaxInstr = 15
    29  )
    30  
    31  func isvar(arg x86asm.Arg) bool {
    32  	v, ok := arg.(x86asm.Mem)
    33  	return ok && v.Base == x86asm.RIP
    34  }
    35  
    36  func iszero(arg x86asm.Arg) bool {
    37  	v, ok := arg.(x86asm.Imm)
    38  	return ok && v == 0
    39  }
    40  
    41  func GcwbAddr() uintptr {
    42  	var err error
    43  	var off uintptr
    44  	var ins x86asm.Inst
    45  
    46  	/* get the function address */
    47  	pc := uintptr(0)
    48  	fp := FuncAddr(atomic.StorePointer)
    49  
    50  	/* search within the first 16 instructions */
    51  	for i := 0; i < 16; i++ {
    52  		mem := unsafe.Pointer(uintptr(fp) + pc)
    53  		buf := BytesFrom(mem, _MaxInstr, _MaxInstr)
    54  
    55  		/* disassemble the instruction */
    56  		if ins, err = x86asm.Decode(buf, 64); err != nil {
    57  			panic("gcwbaddr: " + err.Error())
    58  		}
    59  
    60  		/* check for a byte comparison with zero */
    61  		if ins.Op == x86asm.CMP && ins.MemBytes == 1 && isvar(ins.Args[0]) && iszero(ins.Args[1]) {
    62  			off = pc + uintptr(ins.Len) + uintptr(ins.Args[0].(x86asm.Mem).Disp)
    63  			break
    64  		}
    65  
    66  		/* move to next instruction */
    67  		nb := ins.Len
    68  		pc += uintptr(nb)
    69  	}
    70  
    71  	/* check for address */
    72  	if off == 0 {
    73  		panic("gcwbaddr: could not locate the variable `writeBarrier`")
    74  	} else {
    75  		return uintptr(fp) + off
    76  	}
    77  }
    78  
    79  // StopProfiling is used to stop traceback introduced by SIGPROF while native code is running.
    80  // WARN: this option is only a workaround for traceback issue (https://github.com/goshafaq/sonic/issues/310),
    81  // and will be dropped when the issue is fixed.
    82  var StopProfiling = os.Getenv("SONIC_STOP_PROFILING") != ""
    83  
    84  // WARN: must be aligned with runtime.Prof
    85  // type Prof struct {
    86  //     signalLock uint32
    87  // 	hz int32
    88  // }
    89  
    90  var (
    91  	// // go:linkname runtimeProf runtime.prof
    92  	// runtimeProf Prof
    93  
    94  	// count of native-C calls
    95  	yieldCount uint32
    96  
    97  	// previous value of runtimeProf.hz
    98  	oldHz int32
    99  )
   100  
   101  //go:nosplit
   102  func MoreStack(size uintptr)
   103  
   104  func StopProf()
   105  
   106  // func StopProf() {
   107  //     atomic.AddUint32(&yieldCount, 1)
   108  //     if runtimeProf.hz != 0 {
   109  //         oldHz = runtimeProf.hz
   110  //         runtimeProf.hz = 0
   111  //     }
   112  // }
   113  
   114  func StartProf()
   115  
   116  // func StartProf() {
   117  //     atomic.AddUint32(&yieldCount, ^uint32(0))
   118  //     if yieldCount == 0 && runtimeProf.hz == 0 {
   119  //         if oldHz == 0 {
   120  //             oldHz = 100
   121  //         }
   122  //         runtimeProf.hz = oldHz
   123  //     }
   124  // }