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