github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/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/bytedance/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  // }