blob: 5171dfc72e22af8f3e1c5d3c46f7a5bd0c6309b9 [file] [log] [blame]
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +04001// 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
9package main
10
11import (
12 "runtime"
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040013 "time"
14)
15
16func main() {
Brad Fitzpatrickd2fa9372015-11-02 07:46:44 -080017 // Does not work on gccgo due to partially conservative GC.
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040018 // Try to enable when we have fully precise GC.
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040019 if runtime.Compiler == "gccgo" {
20 return
21 }
Dmitry Vyukovbf606092015-11-03 12:19:15 +010022 const N = 100
23 finalized := make(chan int32, N)
24 for i := 0; i < N; i++ {
Brad Fitzpatrickd2fa9372015-11-02 07:46:44 -080025 x := new(int32) // subject to tiny alloc
Dmitry Vyukovbf606092015-11-03 12:19:15 +010026 *x = int32(i)
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040027 // the closure must be big enough to be combined
Brad Fitzpatrickd2fa9372015-11-02 07:46:44 -080028 runtime.SetFinalizer(x, func(p *int32) {
Dmitry Vyukovbf606092015-11-03 12:19:15 +010029 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:
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040042 // 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).
Dmitry Vyukovbf606092015-11-03 12:19:15 +010045 if x < 0 || x >= N {
46 println("got", x)
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040047 panic("corrupted")
48 }
Dmitry Vyukovbf606092015-11-03 12:19:15 +010049 if done[x] {
50 println("got", x)
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040051 panic("already finalized")
52 }
Dmitry Vyukovbf606092015-11-03 12:19:15 +010053 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 }
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040063 }
64}