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 // }