Albirew/nyaa-pantsu
Archivé
1
0
Bifurcation 0
Ce dépôt a été archivé le 2022-05-07. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d'ajout, ni soumettre de changements.
nyaa-pantsu/vendor/github.com/anacrolix/sync/sync.go
akuma06 a41f938cec Add Godep support (#758)
As we have seen, dependencies version can prevent the build. We should
user lock versions on dependencies that we know work:
* Packages are vendored
* Add Godep support
* Added addtional install step in readme
* Fix travis build error
2017-05-26 13:07:22 +02:00

147 lignes
3,3 Kio
Go

// Package sync records the stack when locks are taken, and when locks are
// blocked on and exports them as pprof profiles "lockHolders" and
// "lockBlockers". if "net/http/pprof" is imported, you can view them at
// /debug/pprof/ on the default HTTP muxer.
//
// The API mirrors that of stdlib "sync". The package can be imported in place
// of "sync", and is enabled by setting the envvar PPROF_SYNC non-empty.
//
// Note that currently RWMutex is treated like a Mutex when the package is
// enabled.
package sync
import (
"fmt"
"io"
"net/http"
"os"
"runtime"
"runtime/pprof"
"sort"
"sync"
"text/tabwriter"
"time"
"github.com/anacrolix/missinggo"
)
var (
// Protects initialization and enabling of the package.
enableMu sync.Mutex
// Whether any of this package is to be active.
enabled = false
// Current lock holders.
lockHolders *pprof.Profile
// Those blocked on acquiring a lock.
lockBlockers *pprof.Profile
// Protects lockTimes.
lockTimesMu sync.Mutex
// The longest time the lock is held for any unique stack.
lockTimes map[[32]uintptr]time.Duration
)
type lockTimesSorter struct {
entries []lockTime
}
func (me *lockTimesSorter) Len() int { return len(me.entries) }
func (me *lockTimesSorter) Less(i, j int) bool {
return me.entries[i].held < me.entries[j].held
}
func (me *lockTimesSorter) Swap(i, j int) {
me.entries[i], me.entries[j] = me.entries[j], me.entries[i]
}
type lockTime struct {
stack [32]uintptr
held time.Duration
}
func sortedLockTimes() []lockTime {
var lts lockTimesSorter
lockTimesMu.Lock()
for stack, held := range lockTimes {
lts.entries = append(lts.entries, lockTime{stack, held})
}
lockTimesMu.Unlock()
sort.Sort(sort.Reverse(&lts))
return lts.entries
}
func PrintLockTimes(w io.Writer) {
lockTimes := sortedLockTimes()
tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
defer tw.Flush()
w = tw
for _, elem := range lockTimes {
fmt.Fprintf(w, "%s\n", elem.held)
missinggo.WriteStack(w, elem.stack[:])
}
}
func Enable() {
enableMu.Lock()
defer enableMu.Unlock()
if enabled {
return
}
lockTimes = make(map[[32]uintptr]time.Duration)
lockHolders = pprof.NewProfile("lockHolders")
lockBlockers = pprof.NewProfile("lockBlockers")
http.DefaultServeMux.HandleFunc("/debug/lockTimes", func(w http.ResponseWriter, r *http.Request) {
PrintLockTimes(w)
})
enabled = true
}
func init() {
if os.Getenv("PPROF_SYNC") != "" {
Enable()
}
}
type Mutex struct {
mu sync.Mutex
hold *int // Unique value for passing to pprof.
stack [32]uintptr // The stack for the current holder.
start time.Time // When the lock was obtained.
entries int // Number of entries returned from runtime.Callers.
}
func (m *Mutex) Lock() {
if !enabled {
m.mu.Lock()
return
}
v := new(int)
lockBlockers.Add(v, 0)
m.mu.Lock()
lockBlockers.Remove(v)
m.hold = v
lockHolders.Add(v, 0)
m.entries = runtime.Callers(2, m.stack[:])
m.start = time.Now()
}
func (m *Mutex) Unlock() {
if enabled {
lockHeld := time.Since(m.start)
var key [32]uintptr
copy(key[:], m.stack[:m.entries])
lockTimesMu.Lock()
if lockHeld > lockTimes[key] {
lockTimes[key] = lockHeld
}
lockTimesMu.Unlock()
lockHolders.Remove(m.hold)
}
m.mu.Unlock()
}
type WaitGroup struct {
sync.WaitGroup
}
type Cond struct {
sync.Cond
}