Skip to content
Snippets Groups Projects
malloc.go 34.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	if size == 0 {
    		throw("persistentalloc: size == 0")
    	}
    
    	if align != 0 {
    		if align&(align-1) != 0 {
    
    			throw("persistentalloc: align is not a power of 2")
    
    		}
    		if align > _PageSize {
    
    			throw("persistentalloc: align is too large")
    
    		}
    	} else {
    		align = 8
    	}
    
    	if size >= maxBlock {
    
    		return (*notInHeap)(sysAlloc(size, sysStat))
    
    	mp := acquirem()
    	var persistent *persistentAlloc
    
    	if mp != nil && mp.p != 0 {
    		persistent = &mp.p.ptr().palloc
    
    	} else {
    		lock(&globalAlloc.mutex)
    		persistent = &globalAlloc.persistentAlloc
    	}
    
    	persistent.off = round(persistent.off, align)
    
    	if persistent.off+size > chunk || persistent.base == nil {
    
    		persistent.base = (*notInHeap)(sysAlloc(chunk, &memstats.other_sys))
    
    			if persistent == &globalAlloc.persistentAlloc {
    				unlock(&globalAlloc.mutex)
    			}
    
    			throw("runtime: cannot allocate memory")
    
    	p := persistent.base.add(persistent.off)
    
    	releasem(mp)
    	if persistent == &globalAlloc.persistentAlloc {
    		unlock(&globalAlloc.mutex)
    	}
    
    	if sysStat != &memstats.other_sys {
    		mSysStatInc(sysStat, size)
    		mSysStatDec(&memstats.other_sys, size)
    
    
    // notInHeap is off-heap memory allocated by a lower-level allocator
    // like sysAlloc or persistentAlloc.
    //
    // In general, it's better to use real types marked as go:notinheap,
    // but this serves as a generic type for situations where that isn't
    // possible (like in the allocators).
    //
    // TODO: Use this as the return type of sysAlloc, persistentAlloc, etc?
    //
    //go:notinheap
    type notInHeap struct{}
    
    func (p *notInHeap) add(bytes uintptr) *notInHeap {
    	return (*notInHeap)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + bytes))
    }