Source file src/runtime/testdata/testgoroutineleakprofile/goker/cockroach7504.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a MIT
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6   * Project: cockroach
     7   * Issue or PR  : https://github.com/cockroachdb/cockroach/pull/7504
     8   * Buggy version: bc963b438cdc3e0ad058a5282358e5aee0595e17
     9   * fix commit-id: cab761b9f5ee5dee1448bc5d6b1d9f5a0ff0bad5
    10   * Flaky: 1/100
    11   */
    12  package main
    13  
    14  import (
    15  	"os"
    16  	"runtime"
    17  	"runtime/pprof"
    18  	"sync"
    19  	"time"
    20  )
    21  
    22  func init() {
    23  	register("Cockroach7504", Cockroach7504)
    24  }
    25  
    26  func MakeCacheKey_cockroach7504(lease *LeaseState_cockroach7504) int {
    27  	return lease.id
    28  }
    29  
    30  type LeaseState_cockroach7504 struct {
    31  	mu sync.Mutex // L1
    32  	id int
    33  }
    34  type LeaseSet_cockroach7504 struct {
    35  	data []*LeaseState_cockroach7504
    36  }
    37  
    38  func (l *LeaseSet_cockroach7504) find(id int) *LeaseState_cockroach7504 {
    39  	return l.data[id]
    40  }
    41  
    42  func (l *LeaseSet_cockroach7504) remove(s *LeaseState_cockroach7504) {
    43  	for i := 0; i < len(l.data); i++ {
    44  		if s == l.data[i] {
    45  			l.data = append(l.data[:i], l.data[i+1:]...)
    46  			break
    47  		}
    48  	}
    49  }
    50  
    51  type tableState_cockroach7504 struct {
    52  	tableNameCache *tableNameCache_cockroach7504
    53  	mu             sync.Mutex // L3
    54  	active         *LeaseSet_cockroach7504
    55  }
    56  
    57  func (t *tableState_cockroach7504) release(lease *LeaseState_cockroach7504) {
    58  	t.mu.Lock()         // L3
    59  	defer t.mu.Unlock() // L3
    60  
    61  	s := t.active.find(MakeCacheKey_cockroach7504(lease))
    62  	s.mu.Lock() // L1
    63  	runtime.Gosched()
    64  	defer s.mu.Unlock() // L1
    65  
    66  	t.removeLease(s)
    67  }
    68  func (t *tableState_cockroach7504) removeLease(lease *LeaseState_cockroach7504) {
    69  	t.active.remove(lease)
    70  	t.tableNameCache.remove(lease) // L1 acquire/release
    71  }
    72  
    73  type tableNameCache_cockroach7504 struct {
    74  	mu     sync.Mutex // L2
    75  	tables map[int]*LeaseState_cockroach7504
    76  }
    77  
    78  func (c *tableNameCache_cockroach7504) get(id int) {
    79  	c.mu.Lock()         // L2
    80  	defer c.mu.Unlock() // L2
    81  	lease, ok := c.tables[id]
    82  	if !ok {
    83  		return
    84  	}
    85  	if lease == nil {
    86  		panic("nil lease in name cache")
    87  	}
    88  	lease.mu.Lock()         // L1
    89  	defer lease.mu.Unlock() // L1
    90  }
    91  
    92  func (c *tableNameCache_cockroach7504) remove(lease *LeaseState_cockroach7504) {
    93  	c.mu.Lock() // L2
    94  	runtime.Gosched()
    95  	defer c.mu.Unlock() // L2
    96  	key := MakeCacheKey_cockroach7504(lease)
    97  	existing, ok := c.tables[key]
    98  	if !ok {
    99  		return
   100  	}
   101  	if existing == lease {
   102  		delete(c.tables, key)
   103  	}
   104  }
   105  
   106  type LeaseManager_cockroach7504 struct {
   107  	_          [64]byte
   108  	tableNames *tableNameCache_cockroach7504
   109  	tables     map[int]*tableState_cockroach7504
   110  }
   111  
   112  func (m *LeaseManager_cockroach7504) AcquireByName(id int) {
   113  	m.tableNames.get(id)
   114  }
   115  
   116  func (m *LeaseManager_cockroach7504) findTableState(lease *LeaseState_cockroach7504) *tableState_cockroach7504 {
   117  	existing, ok := m.tables[lease.id]
   118  	if !ok {
   119  		return nil
   120  	}
   121  	return existing
   122  }
   123  
   124  func (m *LeaseManager_cockroach7504) Release(lease *LeaseState_cockroach7504) {
   125  	t := m.findTableState(lease)
   126  	t.release(lease)
   127  }
   128  func NewLeaseManager_cockroach7504(tname *tableNameCache_cockroach7504, ts *tableState_cockroach7504) *LeaseManager_cockroach7504 {
   129  	mgr := &LeaseManager_cockroach7504{
   130  		tableNames: tname,
   131  		tables:     make(map[int]*tableState_cockroach7504),
   132  	}
   133  	mgr.tables[0] = ts
   134  	return mgr
   135  }
   136  func NewLeaseSet_cockroach7504(n int) *LeaseSet_cockroach7504 {
   137  	lset := &LeaseSet_cockroach7504{}
   138  	for i := 0; i < n; i++ {
   139  		lease := new(LeaseState_cockroach7504)
   140  		lset.data = append(lset.data, lease)
   141  	}
   142  	return lset
   143  }
   144  
   145  func Cockroach7504() {
   146  	prof := pprof.Lookup("goroutineleak")
   147  	defer func() {
   148  		time.Sleep(100 * time.Millisecond)
   149  		prof.WriteTo(os.Stdout, 2)
   150  	}()
   151  	for i := 0; i < 100; i++ {
   152  		go func() {
   153  			leaseNum := 2
   154  			lset := NewLeaseSet_cockroach7504(leaseNum)
   155  
   156  			nc := &tableNameCache_cockroach7504{
   157  				tables: make(map[int]*LeaseState_cockroach7504),
   158  			}
   159  			for i := 0; i < leaseNum; i++ {
   160  				nc.tables[i] = lset.find(i)
   161  			}
   162  
   163  			ts := &tableState_cockroach7504{
   164  				tableNameCache: nc,
   165  				active:         lset,
   166  			}
   167  
   168  			mgr := NewLeaseManager_cockroach7504(nc, ts)
   169  
   170  			// G1
   171  			go func() {
   172  				// lock L2-L1
   173  				mgr.AcquireByName(0)
   174  			}()
   175  
   176  			// G2
   177  			go func() {
   178  				// lock L1-L2
   179  				mgr.Release(lset.find(0))
   180  			}()
   181  		}()
   182  	}
   183  }
   184  

View as plain text