// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Defensive debug-only utility to track that functions run on the
// goroutine that they're supposed to.

package http2

import (
	
	
	
	
	
	
	
)

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

type goroutineLock uint64

func () goroutineLock {
	if !DebugGoroutines {
		return 0
	}
	return goroutineLock(curGoroutineID())
}

func ( goroutineLock) () {
	if !DebugGoroutines {
		return
	}
	if curGoroutineID() != uint64() {
		panic("running on the wrong goroutine")
	}
}

func ( goroutineLock) () {
	if !DebugGoroutines {
		return
	}
	if curGoroutineID() == uint64() {
		panic("running on the wrong goroutine")
	}
}

var goroutineSpace = []byte("goroutine ")

func () uint64 {
	 := littleBuf.Get().(*[]byte)
	defer littleBuf.Put()
	 := *
	 = [:runtime.Stack(, false)]
	// Parse the 4707 out of "goroutine 4707 ["
	 = bytes.TrimPrefix(, goroutineSpace)
	 := bytes.IndexByte(, ' ')
	if  < 0 {
		panic(fmt.Sprintf("No space found in %q", ))
	}
	 = [:]
	,  := parseUintBytes(, 10, 64)
	if  != nil {
		panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", , ))
	}
	return 
}

var littleBuf = sync.Pool{
	New: func() interface{} {
		 := make([]byte, 64)
		return &
	},
}

// parseUintBytes is like strconv.ParseUint, but using a []byte.
func ( []byte,  int,  int) ( uint64,  error) {
	var ,  uint64

	if  == 0 {
		 = int(strconv.IntSize)
	}

	 := 
	switch {
	case len() < 1:
		 = strconv.ErrSyntax
		goto 

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

	case  == 0:
		// Look for octal, hex prefix.
		switch {
		case [0] == '0' && len() > 1 && ([1] == 'x' || [1] == 'X'):
			 = 16
			 = [2:]
			if len() < 1 {
				 = strconv.ErrSyntax
				goto 
			}
		case [0] == '0':
			 = 8
		default:
			 = 10
		}

	default:
		 = errors.New("invalid base " + strconv.Itoa())
		goto 
	}

	 = 0
	 = cutoff64()
	 = 1<<uint() - 1

	for  := 0;  < len(); ++ {
		var  byte
		 := []
		switch {
		case '0' <=  &&  <= '9':
			 =  - '0'
		case 'a' <=  &&  <= 'z':
			 =  - 'a' + 10
		case 'A' <=  &&  <= 'Z':
			 =  - 'A' + 10
		default:
			 = 0
			 = strconv.ErrSyntax
			goto 
		}
		if int() >=  {
			 = 0
			 = strconv.ErrSyntax
			goto 
		}

		if  >=  {
			// n*base overflows
			 = 1<<64 - 1
			 = strconv.ErrRange
			goto 
		}
		 *= uint64()

		 :=  + uint64()
		if  <  ||  >  {
			// n+v overflows
			 = 1<<64 - 1
			 = strconv.ErrRange
			goto 
		}
		 = 
	}

	return , nil

:
	return , &strconv.NumError{Func: "ParseUint", Num: string(), Err: }
}

// Return the first number n such that n*base >= 1<<64.
func ( int) uint64 {
	if  < 2 {
		return 0
	}
	return (1<<64-1)/uint64() + 1
}