modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/tinyfin.go (about)

     1  // run
     2  
     3  // Copyright 2014 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test finalizers work for tiny (combined) allocations.
     8  
     9  package main
    10  
    11  import (
    12  	"runtime"
    13  	"time"
    14  )
    15  
    16  func main() {
    17  	// Does not work on gccgo due to partially conservative GC.
    18  	// Try to enable when we have fully precise GC.
    19  	if runtime.Compiler == "gccgo" {
    20  		return
    21  	}
    22  	const N = 100
    23  	finalized := make(chan int32, N)
    24  	for i := 0; i < N; i++ {
    25  		x := new(int32) // subject to tiny alloc
    26  		*x = int32(i)
    27  		// the closure must be big enough to be combined
    28  		runtime.SetFinalizer(x, func(p *int32) {
    29  			finalized <- *p
    30  		})
    31  	}
    32  	runtime.GC()
    33  	count := 0
    34  	done := make([]bool, N)
    35  	timeout := time.After(5*time.Second)
    36  	for {
    37  		select {
    38  		case <-timeout:
    39  			println("timeout,", count, "finalized so far")
    40  			panic("not all finalizers are called")
    41  		case x := <-finalized:
    42  			// Check that p points to the correct subobject of the tiny allocation.
    43  			// It's a bit tricky, because we can't capture another variable
    44  			// with the expected value (it would be combined as well).
    45  			if x < 0 || x >= N {
    46  				println("got", x)
    47  				panic("corrupted")
    48  			}
    49  			if done[x] {
    50  				println("got", x)
    51  				panic("already finalized")
    52  			}
    53  			done[x] = true
    54  			count++
    55  			if count > N/10*9 {
    56  				// Some of the finalizers may not be executed,
    57  				// if the outermost allocations are combined with something persistent.
    58  				// Currently 4 int32's are combined into a 16-byte block,
    59  				// ensure that most of them are finalized.
    60  				return
    61  			}
    62  		}
    63  	}
    64  }