github.com/Rookout/GoSDK@v0.1.48/pkg/services/callstack/callstack.go (about)

     1  package callstack
     2  
     3  import (
     4  	"github.com/Rookout/GoSDK/pkg/services/suspender"
     5  	"math"
     6  	"runtime"
     7  )
     8  
     9  
    10  const ReallocateSizeAuto int = 0
    11  
    12  type IStackTraceBuffer interface {
    13  	Reallocate(n int)                                      
    14  	FillStackTraces() (n int, ok bool)                     
    15  	Size() int                                             
    16  	GetPC(goroutineIdx, depthIdx int) uintptr              
    17  	GetDepth(goroutineIdx int) (depth int, allFrames bool) 
    18  	GetMaxPossibleDepth() int                              
    19  }
    20  
    21  type StackTraceBuffer struct {
    22  	buf    []runtime.StackRecord
    23  	filled int
    24  }
    25  
    26  func NewStackTraceBuffer() IStackTraceBuffer {
    27  	stb := &StackTraceBuffer{}
    28  	stb.Reallocate(ReallocateSizeAuto)
    29  	return stb
    30  }
    31  
    32  func (s *StackTraceBuffer) Reallocate(n int) {
    33  	if suspender.GetSuspender().Stopped() {
    34  		panic("Can't reallocate when the world is stopped! You must call ResumeAll() first!")
    35  	}
    36  	if n == ReallocateSizeAuto || n < 0 {
    37  		n = runtime.NumGoroutine()
    38  	}
    39  	if n < 1 {
    40  		n = 1
    41  	}
    42  	extraFactor := 1.1 
    43  	n = int(math.Ceil(float64(n) * extraFactor))
    44  	s.buf = make([]runtime.StackRecord, n)
    45  	s.filled = 0
    46  }
    47  
    48  func (s *StackTraceBuffer) capacity() int {
    49  	return len(s.buf)
    50  }
    51  
    52  func (s *StackTraceBuffer) Size() int {
    53  	return s.filled
    54  }
    55  
    56  func (s *StackTraceBuffer) GetPC(goroutineIdx, depthIdx int) uintptr {
    57  	if goroutineIdx >= s.Size() || depthIdx >= len(s.buf[goroutineIdx].Stack0) {
    58  		return 0
    59  	}
    60  	return s.buf[goroutineIdx].Stack0[depthIdx]
    61  }
    62  
    63  func (s *StackTraceBuffer) GetDepth(goroutineIdx int) (depth int, allFrames bool) {
    64  	if goroutineIdx >= s.Size() {
    65  		return 0, false
    66  	}
    67  	buf := &s.buf[goroutineIdx]
    68  	i := 0
    69  	for ; i < len(buf.Stack0); i++ {
    70  		if buf.Stack0[i] == 0 {
    71  			break
    72  		}
    73  	}
    74  	return i, i < len(buf.Stack0)
    75  }
    76  
    77  func (s *StackTraceBuffer) GetMaxPossibleDepth() int {
    78  	if s.capacity() == 0 {
    79  		return 0
    80  	}
    81  	return len(s.buf[0].Stack0)
    82  }