gcwb.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. package rt
  17. import (
  18. `os`
  19. `sync/atomic`
  20. `unsafe`
  21. `golang.org/x/arch/x86/x86asm`
  22. )
  23. const (
  24. _MaxInstr = 15
  25. )
  26. func isvar(arg x86asm.Arg) bool {
  27. v, ok := arg.(x86asm.Mem)
  28. return ok && v.Base == x86asm.RIP
  29. }
  30. func iszero(arg x86asm.Arg) bool {
  31. v, ok := arg.(x86asm.Imm)
  32. return ok && v == 0
  33. }
  34. func GcwbAddr() uintptr {
  35. var err error
  36. var off uintptr
  37. var ins x86asm.Inst
  38. /* get the function address */
  39. pc := uintptr(0)
  40. fp := FuncAddr(atomic.StorePointer)
  41. /* search within the first 16 instructions */
  42. for i := 0; i < 16; i++ {
  43. mem := unsafe.Pointer(uintptr(fp) + pc)
  44. buf := BytesFrom(mem, _MaxInstr, _MaxInstr)
  45. /* disassemble the instruction */
  46. if ins, err = x86asm.Decode(buf, 64); err != nil {
  47. panic("gcwbaddr: " + err.Error())
  48. }
  49. /* check for a byte comparison with zero */
  50. if ins.Op == x86asm.CMP && ins.MemBytes == 1 && isvar(ins.Args[0]) && iszero(ins.Args[1]) {
  51. off = pc + uintptr(ins.Len) + uintptr(ins.Args[0].(x86asm.Mem).Disp)
  52. break
  53. }
  54. /* move to next instruction */
  55. nb := ins.Len
  56. pc += uintptr(nb)
  57. }
  58. /* check for address */
  59. if off == 0 {
  60. panic("gcwbaddr: could not locate the variable `writeBarrier`")
  61. } else {
  62. return uintptr(fp) + off
  63. }
  64. }
  65. // StopProfiling is used to stop traceback introduced by SIGPROF while native code is running.
  66. // WARN: this option is only a workaround for traceback issue (https://github.com/bytedance/sonic/issues/310),
  67. // and will be dropped when the issue is fixed.
  68. var StopProfiling = os.Getenv("SONIC_STOP_PROFILING") != ""
  69. // WARN: must be aligned with runtime.Prof
  70. // type Prof struct {
  71. // signalLock uint32
  72. // hz int32
  73. // }
  74. var (
  75. // // go:linkname runtimeProf runtime.prof
  76. // runtimeProf Prof
  77. // count of native-C calls
  78. yieldCount uint32
  79. // previous value of runtimeProf.hz
  80. oldHz int32
  81. )
  82. //go:nosplit
  83. func MoreStack(size uintptr)
  84. func StopProf()
  85. // func StopProf() {
  86. // atomic.AddUint32(&yieldCount, 1)
  87. // if runtimeProf.hz != 0 {
  88. // oldHz = runtimeProf.hz
  89. // runtimeProf.hz = 0
  90. // }
  91. // }
  92. func StartProf()
  93. // func StartProf() {
  94. // atomic.AddUint32(&yieldCount, ^uint32(0))
  95. // if yieldCount == 0 && runtimeProf.hz == 0 {
  96. // if oldHz == 0 {
  97. // oldHz = 100
  98. // }
  99. // runtimeProf.hz = oldHz
  100. // }
  101. // }