if hchanSize%maxAlign != 0 || elem.align > maxAlign {
throw("makechan: bad alignment")
}
- if size < 0 || (elem.size > 0 && uintptr(size) > (_MaxMem-hchanSize)/elem.size) {
+
+ if size < 0 || uintptr(size) > maxSliceCap(elem.size) || uintptr(size)*elem.size > _MaxMem-hchanSize {
panic(plainError("makechan: size out of range"))
}
+ // Hchan does not contain pointers interesting for GC when elements stored in buf do not contain pointers.
+ // buf points into the same allocation, elemtype is persistent.
+ // SudoG's are referenced from their owning thread so they can't be collected.
+ // TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
var c *hchan
- if elem.kind&kindNoPointers != 0 || size == 0 {
- // Allocate memory in one call.
- // Hchan does not contain pointers interesting for GC in this case:
- // buf points into the same allocation, elemtype is persistent.
- // SudoG's are referenced from their owning thread so they can't be collected.
- // TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
+ switch {
+ case size == 0 || elem.size == 0:
+ // Queue or element size is zero.
+ c = (*hchan)(mallocgc(hchanSize, nil, true))
+ // Race detector uses this location for synchronization.
+ c.buf = unsafe.Pointer(c)
+ case elem.kind&kindNoPointers != 0:
+ // Elements do not contain pointers.
+ // Allocate hchan and buf in one call.
c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))
- if size > 0 && elem.size != 0 {
- c.buf = add(unsafe.Pointer(c), hchanSize)
- } else {
- // race detector uses this location for synchronization
- // Also prevents us from pointing beyond the allocation (see issue 9401).
- c.buf = unsafe.Pointer(c)
- }
- } else {
+ c.buf = add(unsafe.Pointer(c), hchanSize)
+ default:
+ // Elements contain pointers.
c = new(hchan)
- c.buf = newarray(elem, int(size))
+ c.buf = mallocgc(uintptr(size)*elem.size, elem, true)
}
+
c.elemsize = uint16(elem.size)
c.elemtype = elem
c.dataqsiz = uint(size)