github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/testdata/testprogcgo/tracebackctxt.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 // Test the context argument to SetCgoTraceback. 8 // Use fake context, traceback, and symbolizer functions. 9 10 /* 11 // Defined in tracebackctxt_c.c. 12 extern void C1(void); 13 extern void C2(void); 14 extern void tcContext(void*); 15 extern void tcContextSimple(void*); 16 extern void tcTraceback(void*); 17 extern void tcSymbolizer(void*); 18 extern int getContextCount(void); 19 extern void TracebackContextPreemptionCallGo(int); 20 */ 21 import "C" 22 23 import ( 24 "fmt" 25 "runtime" 26 "sync" 27 "unsafe" 28 ) 29 30 func init() { 31 register("TracebackContext", TracebackContext) 32 register("TracebackContextPreemption", TracebackContextPreemption) 33 } 34 35 var tracebackOK bool 36 37 func TracebackContext() { 38 runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContext), unsafe.Pointer(C.tcSymbolizer)) 39 C.C1() 40 if got := C.getContextCount(); got != 0 { 41 fmt.Printf("at end contextCount == %d, expected 0\n", got) 42 tracebackOK = false 43 } 44 if tracebackOK { 45 fmt.Println("OK") 46 } 47 } 48 49 //export G1 50 func G1() { 51 C.C2() 52 } 53 54 //export G2 55 func G2() { 56 pc := make([]uintptr, 32) 57 n := runtime.Callers(0, pc) 58 cf := runtime.CallersFrames(pc[:n]) 59 var frames []runtime.Frame 60 for { 61 frame, more := cf.Next() 62 frames = append(frames, frame) 63 if !more { 64 break 65 } 66 } 67 68 want := []struct { 69 function string 70 line int 71 }{ 72 {"main.G2", 0}, 73 {"cFunction", 0x10200}, 74 {"cFunction", 0x200}, 75 {"cFunction", 0x10201}, 76 {"cFunction", 0x201}, 77 {"main.G1", 0}, 78 {"cFunction", 0x10100}, 79 {"cFunction", 0x100}, 80 {"main.TracebackContext", 0}, 81 } 82 83 ok := true 84 i := 0 85 wantLoop: 86 for _, w := range want { 87 for ; i < len(frames); i++ { 88 if w.function == frames[i].Function { 89 if w.line != 0 && w.line != frames[i].Line { 90 fmt.Printf("found function %s at wrong line %#x (expected %#x)\n", w.function, frames[i].Line, w.line) 91 ok = false 92 } 93 i++ 94 continue wantLoop 95 } 96 } 97 fmt.Printf("did not find function %s in\n", w.function) 98 for _, f := range frames { 99 fmt.Println(f) 100 } 101 ok = false 102 break 103 } 104 tracebackOK = ok 105 if got := C.getContextCount(); got != 2 { 106 fmt.Printf("at bottom contextCount == %d, expected 2\n", got) 107 tracebackOK = false 108 } 109 } 110 111 // Issue 47441. 112 func TracebackContextPreemption() { 113 runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContextSimple), unsafe.Pointer(C.tcSymbolizer)) 114 115 const funcs = 10 116 const calls = 1e5 117 var wg sync.WaitGroup 118 for i := 0; i < funcs; i++ { 119 wg.Add(1) 120 go func(i int) { 121 defer wg.Done() 122 for j := 0; j < calls; j++ { 123 C.TracebackContextPreemptionCallGo(C.int(i*calls + j)) 124 } 125 }(i) 126 } 127 wg.Wait() 128 129 fmt.Println("OK") 130 } 131 132 //export TracebackContextPreemptionGoFunction 133 func TracebackContextPreemptionGoFunction(i C.int) { 134 // Do some busy work. 135 fmt.Sprintf("%d\n", i) 136 }