blob: 3804692a8bf6bd4606236fdb38d404ddc8e6f21d [file] [log] [blame]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"os"
"runtime"
"runtime/pprof"
"sync"
"time"
)
func init() {
register("Hugo3251", Hugo3251)
}
type remoteLock_hugo3251 struct {
sync.RWMutex // L1
m map[string]*sync.Mutex // L2
}
func (l *remoteLock_hugo3251) URLLock(url string) {
l.Lock() // L1
if _, ok := l.m[url]; !ok {
l.m[url] = &sync.Mutex{}
}
l.m[url].Lock() // L2
runtime.Gosched()
l.Unlock() // L1
// runtime.Gosched()
}
func (l *remoteLock_hugo3251) URLUnlock(url string) {
l.RLock() // L1
defer l.RUnlock() // L1
if um, ok := l.m[url]; ok {
um.Unlock() // L2
}
}
func resGetRemote_hugo3251(remoteURLLock *remoteLock_hugo3251, url string) error {
remoteURLLock.URLLock(url)
defer func() { remoteURLLock.URLUnlock(url) }()
return nil
}
func Hugo3251() {
prof := pprof.Lookup("goroutineleak")
defer func() {
time.Sleep(time.Second)
prof.WriteTo(os.Stdout, 2)
}()
for i := 0; i < 11; i++ {
go func() { // G1
url := "http://Foo.Bar/foo_Bar-Foo"
remoteURLLock := &remoteLock_hugo3251{m: make(map[string]*sync.Mutex)}
for range []bool{false, true} {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(gor int) { // G2
defer wg.Done()
for j := 0; j < 200; j++ {
err := resGetRemote_hugo3251(remoteURLLock, url)
if err != nil {
fmt.Errorf("Error getting resource content: %s", err)
}
time.Sleep(300 * time.Nanosecond)
}
}(i)
}
wg.Wait()
}
}()
}
}