}
if w.context != nil && file == fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH) {
// Just enough to keep the api checker happy.
- src := "package runtime; type maptype struct{}; type _type struct{}; type alg struct{}; type mspan struct{}; type m struct{}; type lock struct{}; type slicetype struct{}; type iface struct{}; type eface struct{}; type interfacetype struct{}; type itab struct{}"
+ src := "package runtime; type maptype struct{}; type _type struct{}; type alg struct{};" +
+ " type mspan struct{}; type m struct{}; type lock struct{}; type slicetype struct{};" +
+ " type iface struct{}; type eface struct{}; type interfacetype struct{}; type itab struct{};" +
+ " type mcache struct{}"
f, err = parser.ParseFile(fset, filename, src, 0)
if err != nil {
log.Fatalf("incorrect generated file: %s", err)
if size == 0 {
return unsafe.Pointer(&zeroObject)
}
- mp := acquirem()
- if mp.mallocing != 0 {
- gothrow("malloc/free - deadlock")
- }
- mp.mallocing = 1
size0 := size
- c := mp.mcache
+ // This function must be atomic wrt GC, but for performance reasons
+ // we don't acquirem/releasem on fast path. The code below does not have
+ // split stack checks, so it can't be preempted by GC.
+ // Functions like roundup/add are inlined. And onM/racemalloc are nosplit.
+ // If debugMalloc = true, these assumptions are checked below.
+ if debugMalloc {
+ mp := acquirem()
+ if mp.mallocing != 0 {
+ gothrow("malloc deadlock")
+ }
+ mp.mallocing = 1
+ if mp.curg != nil {
+ mp.curg.stackguard0 = ^uint(0xfff) | 0xbad
+ }
+ }
+
+ c := gomcache()
var s *mspan
var x unsafe.Pointer
if size <= maxSmallSize {
x = tiny
c.tiny = (*byte)(add(x, size))
c.tinysize -= uint(size1)
- mp.mallocing = 0
- releasem(mp)
+ if debugMalloc {
+ mp := acquirem()
+ if mp.mallocing == 0 {
+ gothrow("bad malloc")
+ }
+ mp.mallocing = 0
+ if mp.curg != nil {
+ mp.curg.stackguard0 = mp.curg.stackguard
+ }
+ releasem(mp)
+ releasem(mp)
+ }
return x
}
}
s = c.alloc[tinySizeClass]
v := s.freelist
if v == nil {
+ mp := acquirem()
mp.scalararg[0] = tinySizeClass
onM(&mcacheRefill_m)
+ releasem(mp)
s = c.alloc[tinySizeClass]
v = s.freelist
}
s = c.alloc[sizeclass]
v := s.freelist
if v == nil {
+ mp := acquirem()
mp.scalararg[0] = uint(sizeclass)
onM(&mcacheRefill_m)
+ releasem(mp)
s = c.alloc[sizeclass]
v = s.freelist
}
}
c.local_cachealloc += int(size)
} else {
+ mp := acquirem()
mp.scalararg[0] = uint(size)
mp.scalararg[1] = uint(flags)
onM(&largeAlloc_m)
s = (*mspan)(mp.ptrarg[0])
mp.ptrarg[0] = nil
+ releasem(mp)
x = unsafe.Pointer(uintptr(s.start << pageShift))
size = uintptr(s.elemsize)
}
// into the GC bitmap. It's 7 times slower than copying
// from the pre-unrolled mask, but saves 1/16 of type size
// memory for the mask.
+ mp := acquirem()
mp.ptrarg[0] = x
mp.ptrarg[1] = unsafe.Pointer(typ)
mp.scalararg[0] = uint(size)
mp.scalararg[1] = uint(size0)
onM(&unrollgcproginplace_m)
+ releasem(mp)
goto marked
}
ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0])))
// Check whether the program is already unrolled.
if uintptr(goatomicloadp(unsafe.Pointer(ptrmask)))&0xff == 0 {
+ mp := acquirem()
mp.ptrarg[0] = unsafe.Pointer(typ)
onM(&unrollgcprog_m)
+ releasem(mp)
}
ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
} else {
}
}
marked:
- mp.mallocing = 0
-
if raceenabled {
racemalloc(x, size)
}
+
+ if debugMalloc {
+ mp := acquirem()
+ if mp.mallocing == 0 {
+ gothrow("bad malloc")
+ }
+ mp.mallocing = 0
+ if mp.curg != nil {
+ mp.curg.stackguard0 = mp.curg.stackguard
+ }
+ releasem(mp)
+ releasem(mp)
+ }
+
if debug.allocfreetrace != 0 {
tracealloc(x, size, typ)
}
if size < uintptr(rate) && int32(size) < c.next_sample {
c.next_sample -= int32(size)
} else {
+ mp := acquirem()
profilealloc(mp, x, size)
+ releasem(mp)
}
}
- releasem(mp)
-
if memstats.heap_alloc >= memstats.next_gc {
gogc(0)
}