cubefs

Форк
0
170 строк · 3.1 Кб
1
// Copyright 2014 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
// Defensive debug-only utility to track that functions run on the
6
// goroutine that they're supposed to.
7

8
package http2
9

10
import (
11
	"bytes"
12
	"errors"
13
	"fmt"
14
	"os"
15
	"runtime"
16
	"strconv"
17
	"sync"
18
)
19

20
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
21

22
type goroutineLock uint64
23

24
func newGoroutineLock() goroutineLock {
25
	if !DebugGoroutines {
26
		return 0
27
	}
28
	return goroutineLock(curGoroutineID())
29
}
30

31
func (g goroutineLock) check() {
32
	if !DebugGoroutines {
33
		return
34
	}
35
	if curGoroutineID() != uint64(g) {
36
		panic("running on the wrong goroutine")
37
	}
38
}
39

40
func (g goroutineLock) checkNotOn() {
41
	if !DebugGoroutines {
42
		return
43
	}
44
	if curGoroutineID() == uint64(g) {
45
		panic("running on the wrong goroutine")
46
	}
47
}
48

49
var goroutineSpace = []byte("goroutine ")
50

51
func curGoroutineID() uint64 {
52
	bp := littleBuf.Get().(*[]byte)
53
	defer littleBuf.Put(bp)
54
	b := *bp
55
	b = b[:runtime.Stack(b, false)]
56
	// Parse the 4707 out of "goroutine 4707 ["
57
	b = bytes.TrimPrefix(b, goroutineSpace)
58
	i := bytes.IndexByte(b, ' ')
59
	if i < 0 {
60
		panic(fmt.Sprintf("No space found in %q", b))
61
	}
62
	b = b[:i]
63
	n, err := parseUintBytes(b, 10, 64)
64
	if err != nil {
65
		panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
66
	}
67
	return n
68
}
69

70
var littleBuf = sync.Pool{
71
	New: func() interface{} {
72
		buf := make([]byte, 64)
73
		return &buf
74
	},
75
}
76

77
// parseUintBytes is like strconv.ParseUint, but using a []byte.
78
func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
79
	var cutoff, maxVal uint64
80

81
	if bitSize == 0 {
82
		bitSize = int(strconv.IntSize)
83
	}
84

85
	s0 := s
86
	switch {
87
	case len(s) < 1:
88
		err = strconv.ErrSyntax
89
		goto Error
90

91
	case 2 <= base && base <= 36:
92
		// valid base; nothing to do
93

94
	case base == 0:
95
		// Look for octal, hex prefix.
96
		switch {
97
		case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
98
			base = 16
99
			s = s[2:]
100
			if len(s) < 1 {
101
				err = strconv.ErrSyntax
102
				goto Error
103
			}
104
		case s[0] == '0':
105
			base = 8
106
		default:
107
			base = 10
108
		}
109

110
	default:
111
		err = errors.New("invalid base " + strconv.Itoa(base))
112
		goto Error
113
	}
114

115
	n = 0
116
	cutoff = cutoff64(base)
117
	maxVal = 1<<uint(bitSize) - 1
118

119
	for i := 0; i < len(s); i++ {
120
		var v byte
121
		d := s[i]
122
		switch {
123
		case '0' <= d && d <= '9':
124
			v = d - '0'
125
		case 'a' <= d && d <= 'z':
126
			v = d - 'a' + 10
127
		case 'A' <= d && d <= 'Z':
128
			v = d - 'A' + 10
129
		default:
130
			n = 0
131
			err = strconv.ErrSyntax
132
			goto Error
133
		}
134
		if int(v) >= base {
135
			n = 0
136
			err = strconv.ErrSyntax
137
			goto Error
138
		}
139

140
		if n >= cutoff {
141
			// n*base overflows
142
			n = 1<<64 - 1
143
			err = strconv.ErrRange
144
			goto Error
145
		}
146
		n *= uint64(base)
147

148
		n1 := n + uint64(v)
149
		if n1 < n || n1 > maxVal {
150
			// n+v overflows
151
			n = 1<<64 - 1
152
			err = strconv.ErrRange
153
			goto Error
154
		}
155
		n = n1
156
	}
157

158
	return n, nil
159

160
Error:
161
	return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
162
}
163

164
// Return the first number n such that n*base >= 1<<64.
165
func cutoff64(base int) uint64 {
166
	if base < 2 {
167
		return 0
168
	}
169
	return (1<<64-1)/uint64(base) + 1
170
}
171

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.