github.com/brownsys/tracing-framework-go@v0.0.0-20161210174012-0542a62412fe/other/internal/gls/gls_shim.go (about) 1 // +build !goid 2 3 package gls 4 5 import ( 6 "fmt" 7 "runtime" 8 "unsafe" 9 ) 10 11 func _go(f func()) { 12 go base(f) 13 } 14 15 type shim func([]shim) 16 17 func base(f func()) { 18 m := make(map[interface{}]interface{}) 19 ptr := uintptr(unsafe.Pointer(&m)) 20 21 var s []shim 22 23 switch runtime.GOARCH { 24 case "386": 25 s = make([]shim, 4) 26 s[0] = shims[int((ptr>>8)&0xFF)] 27 s[1] = shims[int((ptr>>16)&0xFF)] 28 s[2] = shims[int((ptr>>24)&0xFF)] 29 case "amd64": 30 s = make([]shim, 8) 31 s[0] = shims[int((ptr>>8)&0xFF)] 32 s[1] = shims[int((ptr>>16)&0xFF)] 33 s[2] = shims[int((ptr>>24)&0xFF)] 34 s[3] = shims[int((ptr>>32)&0xFF)] 35 s[4] = shims[int((ptr>>40)&0xFF)] 36 s[5] = shims[int((ptr>>48)&0xFF)] 37 s[6] = shims[int((ptr>>56)&0xFF)] 38 default: 39 panic(fmt.Errorf("gls: unsupported GOARCH %v", runtime.GOARCH)) 40 } 41 s[len(s)-1] = func(_ []shim) { f() } 42 43 shims[int(ptr&0xFF)](s) 44 45 // use m so the compiler can't optimize 46 // it away (since we're using an unsafe pointer) 47 m[1] = 1 48 } 49 50 var basePtr uintptr 51 52 func init() { 53 skip := 3 54 switch runtime.GOARCH { 55 case "386": 56 skip += 4 57 case "amd64": 58 skip += 8 59 default: 60 panic(fmt.Errorf("gls: unsupported GOARCH %v", runtime.GOARCH)) 61 } 62 f := func() { 63 pcs := make([]uintptr, 16) 64 runtime.Callers(skip, pcs) 65 basePtr = pcs[0] 66 } 67 base(f) 68 } 69 70 var pcToUintptr = make(map[uintptr]uintptr) 71 72 var shimPCOffset uintptr 73 74 // getPtr computes the current goroutine's 75 // goroutine-local pointer 76 func getPtr() uintptr { 77 var pcs [16]uintptr 78 // we know we can at least skip this 79 // call and the call to getPtr 80 i := runtime.Callers(2, pcs[:]) 81 82 if i < 2 || pcs[i-2] != basePtr { 83 panic("gls: no local storage associated with this goroutine") 84 } 85 // we don't care about runtime.goexit or base, 86 // and we want i to be the index of the last 87 // element, not the length 88 i -= 3 89 90 var ptr uintptr 91 switch runtime.GOARCH { 92 case "386": 93 ptr |= pcToUintptr[pcs[i]] 94 ptr |= pcToUintptr[pcs[i-1]] << 8 95 ptr |= pcToUintptr[pcs[i-2]] << 16 96 ptr |= pcToUintptr[pcs[i-3]] << 24 97 case "amd64": 98 ptr |= pcToUintptr[pcs[i]] 99 ptr |= pcToUintptr[pcs[i-1]] << 8 100 ptr |= pcToUintptr[pcs[i-2]] << 16 101 ptr |= pcToUintptr[pcs[i-3]] << 24 102 ptr |= pcToUintptr[pcs[i-4]] << 32 103 ptr |= pcToUintptr[pcs[i-5]] << 40 104 ptr |= pcToUintptr[pcs[i-6]] << 48 105 ptr |= pcToUintptr[pcs[i-7]] << 56 106 default: 107 panic(fmt.Errorf("gls: unsupported GOARCH %v", runtime.GOARCH)) 108 } 109 110 return ptr 111 } 112 113 func put(k, v interface{}) { 114 ptr := getPtr() 115 m := *(*map[interface{}]interface{})(unsafe.Pointer(ptr)) 116 m[k] = v 117 } 118 119 func get(k interface{}) (interface{}, bool) { 120 ptr := getPtr() 121 m := *(*map[interface{}]interface{})(unsafe.Pointer(ptr)) 122 v, ok := m[k] 123 return v, ok 124 } 125 126 func del(k interface{}) { 127 ptr := getPtr() 128 m := *(*map[interface{}]interface{})(unsafe.Pointer(ptr)) 129 delete(m, k) 130 }