Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 The Go Authors.  All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Garbage collector: finalizers and block profiling.
      6 
      7 package runtime
      8 
      9 import "unsafe"
     10 
     11 type finblock struct {
     12 	alllink *finblock
     13 	next    *finblock
     14 	cnt     int32
     15 	_       int32
     16 	fin     [(_FinBlockSize - 2*ptrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer
     17 }
     18 
     19 var finlock mutex  // protects the following variables
     20 var fing *g        // goroutine that runs finalizers
     21 var finq *finblock // list of finalizers that are to be executed
     22 var finc *finblock // cache of free blocks
     23 var finptrmask [_FinBlockSize / ptrSize / 8]byte
     24 var fingwait bool
     25 var fingwake bool
     26 var allfin *finblock // list of all blocks
     27 
     28 // NOTE: Layout known to queuefinalizer.
     29 type finalizer struct {
     30 	fn   *funcval       // function to call
     31 	arg  unsafe.Pointer // ptr to object
     32 	nret uintptr        // bytes of return values from fn
     33 	fint *_type         // type of first argument of fn
     34 	ot   *ptrtype       // type of ptr to object
     35 }
     36 
     37 var finalizer1 = [...]byte{
     38 	// Each Finalizer is 5 words, ptr ptr INT ptr ptr (INT = uintptr here)
     39 	// Each byte describes 8 words.
     40 	// Need 8 Finalizers described by 5 bytes before pattern repeats:
     41 	//	ptr ptr INT ptr ptr
     42 	//	ptr ptr INT ptr ptr
     43 	//	ptr ptr INT ptr ptr
     44 	//	ptr ptr INT ptr ptr
     45 	//	ptr ptr INT ptr ptr
     46 	//	ptr ptr INT ptr ptr
     47 	//	ptr ptr INT ptr ptr
     48 	//	ptr ptr INT ptr ptr
     49 	// aka
     50 	//
     51 	//	ptr ptr INT ptr ptr ptr ptr INT
     52 	//	ptr ptr ptr ptr INT ptr ptr ptr
     53 	//	ptr INT ptr ptr ptr ptr INT ptr
     54 	//	ptr ptr ptr INT ptr ptr ptr ptr
     55 	//	INT ptr ptr ptr ptr INT ptr ptr
     56 	//
     57 	// Assumptions about Finalizer layout checked below.
     58 	1<<0 | 1<<1 | 0<<2 | 1<<3 | 1<<4 | 1<<5 | 1<<6 | 0<<7,
     59 	1<<0 | 1<<1 | 1<<2 | 1<<3 | 0<<4 | 1<<5 | 1<<6 | 1<<7,
     60 	1<<0 | 0<<1 | 1<<2 | 1<<3 | 1<<4 | 1<<5 | 0<<6 | 1<<7,
     61 	1<<0 | 1<<1 | 1<<2 | 0<<3 | 1<<4 | 1<<5 | 1<<6 | 1<<7,
     62 	0<<0 | 1<<1 | 1<<2 | 1<<3 | 1<<4 | 0<<5 | 1<<6 | 1<<7,
     63 }
     64 
     65 func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot *ptrtype) {
     66 	lock(&finlock)
     67 	if finq == nil || finq.cnt == int32(len(finq.fin)) {
     68 		if finc == nil {
     69 			// Note: write barrier here, assigning to finc, but should be okay.
     70 			finc = (*finblock)(persistentalloc(_FinBlockSize, 0, &memstats.gc_sys))
     71 			finc.alllink = allfin
     72 			allfin = finc
     73 			if finptrmask[0] == 0 {
     74 				// Build pointer mask for Finalizer array in block.
     75 				// Check assumptions made in finalizer1 array above.
     76 				if (unsafe.Sizeof(finalizer{}) != 5*ptrSize ||
     77 					unsafe.Offsetof(finalizer{}.fn) != 0 ||
     78 					unsafe.Offsetof(finalizer{}.arg) != ptrSize ||
     79 					unsafe.Offsetof(finalizer{}.nret) != 2*ptrSize ||
     80 					unsafe.Offsetof(finalizer{}.fint) != 3*ptrSize ||
     81 					unsafe.Offsetof(finalizer{}.ot) != 4*ptrSize) {
     82 					throw("finalizer out of sync")
     83 				}
     84 				for i := range finptrmask {
     85 					finptrmask[i] = finalizer1[i%len(finalizer1)]
     86 				}
     87 			}
     88 		}
     89 		block := finc
     90 		finc = block.next
     91 		block.next = finq
     92 		finq = block
     93 	}
     94 	f := &finq.fin[finq.cnt]
     95 	finq.cnt++
     96 	f.fn = fn
     97 	f.nret = nret
     98 	f.fint = fint
     99 	f.ot = ot
    100 	f.arg = p
    101 	fingwake = true
    102 	unlock(&finlock)
    103 }
    104 
    105 //go:nowritebarrier
    106 func iterate_finq(callback func(*funcval, unsafe.Pointer, uintptr, *_type, *ptrtype)) {
    107 	for fb := allfin; fb != nil; fb = fb.alllink {
    108 		for i := int32(0); i < fb.cnt; i++ {
    109 			f := &fb.fin[i]
    110 			callback(f.fn, f.arg, f.nret, f.fint, f.ot)
    111 		}
    112 	}
    113 }
    114 
    115 func wakefing() *g {
    116 	var res *g
    117 	lock(&finlock)
    118 	if fingwait && fingwake {
    119 		fingwait = false
    120 		fingwake = false
    121 		res = fing
    122 	}
    123 	unlock(&finlock)
    124 	return res
    125 }
    126 
    127 var (
    128 	fingCreate  uint32
    129 	fingRunning bool
    130 )
    131 
    132 func createfing() {
    133 	// start the finalizer goroutine exactly once
    134 	if fingCreate == 0 && cas(&fingCreate, 0, 1) {
    135 		go runfinq()
    136 	}
    137 }
    138 
    139 // This is the goroutine that runs all of the finalizers
    140 func runfinq() {
    141 	var (
    142 		frame    unsafe.Pointer
    143 		framecap uintptr
    144 	)
    145 
    146 	for {
    147 		lock(&finlock)
    148 		fb := finq
    149 		finq = nil
    150 		if fb == nil {
    151 			gp := getg()
    152 			fing = gp
    153 			fingwait = true
    154 			goparkunlock(&finlock, "finalizer wait", traceEvGoBlock, 1)
    155 			continue
    156 		}
    157 		unlock(&finlock)
    158 		if raceenabled {
    159 			racefingo()
    160 		}
    161 		for fb != nil {
    162 			for i := fb.cnt; i > 0; i-- {
    163 				f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i-1)*unsafe.Sizeof(finalizer{})))
    164 
    165 				framesz := unsafe.Sizeof((interface{})(nil)) + uintptr(f.nret)
    166 				if framecap < framesz {
    167 					// The frame does not contain pointers interesting for GC,
    168 					// all not yet finalized objects are stored in finq.
    169 					// If we do not mark it as FlagNoScan,
    170 					// the last finalized object is not collected.
    171 					frame = mallocgc(framesz, nil, flagNoScan)
    172 					framecap = framesz
    173 				}
    174 
    175 				if f.fint == nil {
    176 					throw("missing type in runfinq")
    177 				}
    178 				switch f.fint.kind & kindMask {
    179 				case kindPtr:
    180 					// direct use of pointer
    181 					*(*unsafe.Pointer)(frame) = f.arg
    182 				case kindInterface:
    183 					ityp := (*interfacetype)(unsafe.Pointer(f.fint))
    184 					// set up with empty interface
    185 					(*eface)(frame)._type = &f.ot.typ
    186 					(*eface)(frame).data = f.arg
    187 					if len(ityp.mhdr) != 0 {
    188 						// convert to interface with methods
    189 						// this conversion is guaranteed to succeed - we checked in SetFinalizer
    190 						assertE2I(ityp, *(*interface{})(frame), (*fInterface)(frame))
    191 					}
    192 				default:
    193 					throw("bad kind in runfinq")
    194 				}
    195 				fingRunning = true
    196 				reflectcall(nil, unsafe.Pointer(f.fn), frame, uint32(framesz), uint32(framesz))
    197 				fingRunning = false
    198 
    199 				// drop finalizer queue references to finalized object
    200 				f.fn = nil
    201 				f.arg = nil
    202 				f.ot = nil
    203 				fb.cnt = i - 1
    204 			}
    205 			next := fb.next
    206 			lock(&finlock)
    207 			fb.next = finc
    208 			finc = fb
    209 			unlock(&finlock)
    210 			fb = next
    211 		}
    212 	}
    213 }
    214 
    215 // SetFinalizer sets the finalizer associated with x to f.
    216 // When the garbage collector finds an unreachable block
    217 // with an associated finalizer, it clears the association and runs
    218 // f(x) in a separate goroutine.  This makes x reachable again, but
    219 // now without an associated finalizer.  Assuming that SetFinalizer
    220 // is not called again, the next time the garbage collector sees
    221 // that x is unreachable, it will free x.
    222 //
    223 // SetFinalizer(x, nil) clears any finalizer associated with x.
    224 //
    225 // The argument x must be a pointer to an object allocated by
    226 // calling new or by taking the address of a composite literal.
    227 // The argument f must be a function that takes a single argument
    228 // to which x's type can be assigned, and can have arbitrary ignored return
    229 // values. If either of these is not true, SetFinalizer aborts the
    230 // program.
    231 //
    232 // Finalizers are run in dependency order: if A points at B, both have
    233 // finalizers, and they are otherwise unreachable, only the finalizer
    234 // for A runs; once A is freed, the finalizer for B can run.
    235 // If a cyclic structure includes a block with a finalizer, that
    236 // cycle is not guaranteed to be garbage collected and the finalizer
    237 // is not guaranteed to run, because there is no ordering that
    238 // respects the dependencies.
    239 //
    240 // The finalizer for x is scheduled to run at some arbitrary time after
    241 // x becomes unreachable.
    242 // There is no guarantee that finalizers will run before a program exits,
    243 // so typically they are useful only for releasing non-memory resources
    244 // associated with an object during a long-running program.
    245 // For example, an os.File object could use a finalizer to close the
    246 // associated operating system file descriptor when a program discards
    247 // an os.File without calling Close, but it would be a mistake
    248 // to depend on a finalizer to flush an in-memory I/O buffer such as a
    249 // bufio.Writer, because the buffer would not be flushed at program exit.
    250 //
    251 // It is not guaranteed that a finalizer will run if the size of *x is
    252 // zero bytes.
    253 //
    254 // It is not guaranteed that a finalizer will run for objects allocated
    255 // in initializers for package-level variables. Such objects may be
    256 // linker-allocated, not heap-allocated.
    257 //
    258 // A single goroutine runs all finalizers for a program, sequentially.
    259 // If a finalizer must run for a long time, it should do so by starting
    260 // a new goroutine.
    261 func SetFinalizer(obj interface{}, finalizer interface{}) {
    262 	if debug.sbrk != 0 {
    263 		// debug.sbrk never frees memory, so no finalizers run
    264 		// (and we don't have the data structures to record them).
    265 		return
    266 	}
    267 	e := (*eface)(unsafe.Pointer(&obj))
    268 	etyp := e._type
    269 	if etyp == nil {
    270 		throw("runtime.SetFinalizer: first argument is nil")
    271 	}
    272 	if etyp.kind&kindMask != kindPtr {
    273 		throw("runtime.SetFinalizer: first argument is " + *etyp._string + ", not pointer")
    274 	}
    275 	ot := (*ptrtype)(unsafe.Pointer(etyp))
    276 	if ot.elem == nil {
    277 		throw("nil elem type!")
    278 	}
    279 
    280 	// find the containing object
    281 	_, base, _ := findObject(e.data)
    282 
    283 	if base == nil {
    284 		// 0-length objects are okay.
    285 		if e.data == unsafe.Pointer(&zerobase) {
    286 			return
    287 		}
    288 
    289 		// Global initializers might be linker-allocated.
    290 		//	var Foo = &Object{}
    291 		//	func main() {
    292 		//		runtime.SetFinalizer(Foo, nil)
    293 		//	}
    294 		// The relevant segments are: noptrdata, data, bss, noptrbss.
    295 		// We cannot assume they are in any order or even contiguous,
    296 		// due to external linking.
    297 		for datap := &firstmoduledata; datap != nil; datap = datap.next {
    298 			if datap.noptrdata <= uintptr(e.data) && uintptr(e.data) < datap.enoptrdata ||
    299 				datap.data <= uintptr(e.data) && uintptr(e.data) < datap.edata ||
    300 				datap.bss <= uintptr(e.data) && uintptr(e.data) < datap.ebss ||
    301 				datap.noptrbss <= uintptr(e.data) && uintptr(e.data) < datap.enoptrbss {
    302 				return
    303 			}
    304 		}
    305 		throw("runtime.SetFinalizer: pointer not in allocated block")
    306 	}
    307 
    308 	if e.data != base {
    309 		// As an implementation detail we allow to set finalizers for an inner byte
    310 		// of an object if it could come from tiny alloc (see mallocgc for details).
    311 		if ot.elem == nil || ot.elem.kind&kindNoPointers == 0 || ot.elem.size >= maxTinySize {
    312 			throw("runtime.SetFinalizer: pointer not at beginning of allocated block")
    313 		}
    314 	}
    315 
    316 	f := (*eface)(unsafe.Pointer(&finalizer))
    317 	ftyp := f._type
    318 	if ftyp == nil {
    319 		// switch to system stack and remove finalizer
    320 		systemstack(func() {
    321 			removefinalizer(e.data)
    322 		})
    323 		return
    324 	}
    325 
    326 	if ftyp.kind&kindMask != kindFunc {
    327 		throw("runtime.SetFinalizer: second argument is " + *ftyp._string + ", not a function")
    328 	}
    329 	ft := (*functype)(unsafe.Pointer(ftyp))
    330 	ins := *(*[]*_type)(unsafe.Pointer(&ft.in))
    331 	if ft.dotdotdot || len(ins) != 1 {
    332 		throw("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
    333 	}
    334 	fint := ins[0]
    335 	switch {
    336 	case fint == etyp:
    337 		// ok - same type
    338 		goto okarg
    339 	case fint.kind&kindMask == kindPtr:
    340 		if (fint.x == nil || fint.x.name == nil || etyp.x == nil || etyp.x.name == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
    341 			// ok - not same type, but both pointers,
    342 			// one or the other is unnamed, and same element type, so assignable.
    343 			goto okarg
    344 		}
    345 	case fint.kind&kindMask == kindInterface:
    346 		ityp := (*interfacetype)(unsafe.Pointer(fint))
    347 		if len(ityp.mhdr) == 0 {
    348 			// ok - satisfies empty interface
    349 			goto okarg
    350 		}
    351 		if assertE2I2(ityp, obj, nil) {
    352 			goto okarg
    353 		}
    354 	}
    355 	throw("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
    356 okarg:
    357 	// compute size needed for return parameters
    358 	nret := uintptr(0)
    359 	for _, t := range *(*[]*_type)(unsafe.Pointer(&ft.out)) {
    360 		nret = round(nret, uintptr(t.align)) + uintptr(t.size)
    361 	}
    362 	nret = round(nret, ptrSize)
    363 
    364 	// make sure we have a finalizer goroutine
    365 	createfing()
    366 
    367 	systemstack(func() {
    368 		if !addfinalizer(e.data, (*funcval)(f.data), nret, fint, ot) {
    369 			throw("runtime.SetFinalizer: finalizer already set")
    370 		}
    371 	})
    372 }
    373 
    374 // Look up pointer v in heap.  Return the span containing the object,
    375 // the start of the object, and the size of the object.  If the object
    376 // does not exist, return nil, nil, 0.
    377 func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
    378 	c := gomcache()
    379 	c.local_nlookup++
    380 	if ptrSize == 4 && c.local_nlookup >= 1<<30 {
    381 		// purge cache stats to prevent overflow
    382 		lock(&mheap_.lock)
    383 		purgecachedstats(c)
    384 		unlock(&mheap_.lock)
    385 	}
    386 
    387 	// find span
    388 	arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
    389 	arena_used := uintptr(unsafe.Pointer(mheap_.arena_used))
    390 	if uintptr(v) < arena_start || uintptr(v) >= arena_used {
    391 		return
    392 	}
    393 	p := uintptr(v) >> pageShift
    394 	q := p - arena_start>>pageShift
    395 	s = *(**mspan)(add(unsafe.Pointer(mheap_.spans), q*ptrSize))
    396 	if s == nil {
    397 		return
    398 	}
    399 	x = unsafe.Pointer(uintptr(s.start) << pageShift)
    400 
    401 	if uintptr(v) < uintptr(x) || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != mSpanInUse {
    402 		s = nil
    403 		x = nil
    404 		return
    405 	}
    406 
    407 	n = uintptr(s.elemsize)
    408 	if s.sizeclass != 0 {
    409 		x = add(x, (uintptr(v)-uintptr(x))/n*n)
    410 	}
    411 	return
    412 }
    413