github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/src/runtime/mem_plan9.go (about)

     1  // Copyright 2010 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  package runtime
     6  
     7  import "unsafe"
     8  
     9  const memDebug = false
    10  
    11  var bloc uintptr
    12  var memlock mutex
    13  
    14  type memHdr struct {
    15  	next *memHdr
    16  	size uintptr
    17  }
    18  
    19  var memFreelist *memHdr // sorted in ascending order
    20  
    21  func memAlloc(n uintptr) unsafe.Pointer {
    22  	n = memRound(n)
    23  	var prevp *memHdr
    24  	for p := memFreelist; p != nil; p = p.next {
    25  		if p.size >= n {
    26  			if p.size == n {
    27  				if prevp != nil {
    28  					prevp.next = p.next
    29  				} else {
    30  					memFreelist = p.next
    31  				}
    32  			} else {
    33  				p.size -= n
    34  				p = (*memHdr)(add(unsafe.Pointer(p), p.size))
    35  			}
    36  			memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{}))
    37  			return unsafe.Pointer(p)
    38  		}
    39  		prevp = p
    40  	}
    41  	return sbrk(n)
    42  }
    43  
    44  func memFree(ap unsafe.Pointer, n uintptr) {
    45  	n = memRound(n)
    46  	memclr(ap, n)
    47  	bp := (*memHdr)(ap)
    48  	bp.size = n
    49  	bpn := uintptr(ap)
    50  	if memFreelist == nil {
    51  		bp.next = nil
    52  		memFreelist = bp
    53  		return
    54  	}
    55  	p := memFreelist
    56  	if bpn < uintptr(unsafe.Pointer(p)) {
    57  		memFreelist = bp
    58  		if bpn+bp.size == uintptr(unsafe.Pointer(p)) {
    59  			bp.size += p.size
    60  			bp.next = p.next
    61  			memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{}))
    62  		} else {
    63  			bp.next = p
    64  		}
    65  		return
    66  	}
    67  	for ; p.next != nil; p = p.next {
    68  		if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) {
    69  			break
    70  		}
    71  	}
    72  	if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) {
    73  		bp.size += p.next.size
    74  		bp.next = p.next.next
    75  		memclr(unsafe.Pointer(p.next), unsafe.Sizeof(memHdr{}))
    76  	} else {
    77  		bp.next = p.next
    78  	}
    79  	if uintptr(unsafe.Pointer(p))+p.size == bpn {
    80  		p.size += bp.size
    81  		p.next = bp.next
    82  		memclr(unsafe.Pointer(bp), unsafe.Sizeof(memHdr{}))
    83  	} else {
    84  		p.next = bp
    85  	}
    86  }
    87  
    88  func memCheck() {
    89  	if memDebug == false {
    90  		return
    91  	}
    92  	for p := memFreelist; p != nil && p.next != nil; p = p.next {
    93  		if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) {
    94  			print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n")
    95  			throw("mem: infinite loop")
    96  		}
    97  		if uintptr(unsafe.Pointer(p)) > uintptr(unsafe.Pointer(p.next)) {
    98  			print("runtime: ", unsafe.Pointer(p), " > ", unsafe.Pointer(p.next), "\n")
    99  			throw("mem: unordered list")
   100  		}
   101  		if uintptr(unsafe.Pointer(p))+p.size > uintptr(unsafe.Pointer(p.next)) {
   102  			print("runtime: ", unsafe.Pointer(p), "+", p.size, " > ", unsafe.Pointer(p.next), "\n")
   103  			throw("mem: overlapping blocks")
   104  		}
   105  		for b := add(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})); uintptr(b) < uintptr(unsafe.Pointer(p))+p.size; b = add(b, 1) {
   106  			if *(*byte)(b) != 0 {
   107  				print("runtime: value at addr ", b, " with offset ", uintptr(b)-uintptr(unsafe.Pointer(p)), " in block ", p, " of size ", p.size, " is not zero\n")
   108  				throw("mem: uninitialised memory")
   109  			}
   110  		}
   111  	}
   112  }
   113  
   114  func memRound(p uintptr) uintptr {
   115  	return (p + _PAGESIZE - 1) &^ (_PAGESIZE - 1)
   116  }
   117  
   118  func initBloc() {
   119  	bloc = memRound(firstmoduledata.end)
   120  }
   121  
   122  func sbrk(n uintptr) unsafe.Pointer {
   123  	// Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
   124  	bl := bloc
   125  	n = memRound(n)
   126  	if brk_(unsafe.Pointer(bl+n)) < 0 {
   127  		return nil
   128  	}
   129  	bloc += n
   130  	return unsafe.Pointer(bl)
   131  }
   132  
   133  func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
   134  	lock(&memlock)
   135  	p := memAlloc(n)
   136  	memCheck()
   137  	unlock(&memlock)
   138  	if p != nil {
   139  		mSysStatInc(sysStat, n)
   140  	}
   141  	return p
   142  }
   143  
   144  func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) {
   145  	mSysStatDec(sysStat, n)
   146  	lock(&memlock)
   147  	memFree(v, n)
   148  	memCheck()
   149  	unlock(&memlock)
   150  }
   151  
   152  func sysUnused(v unsafe.Pointer, n uintptr) {
   153  }
   154  
   155  func sysUsed(v unsafe.Pointer, n uintptr) {
   156  }
   157  
   158  func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
   159  	// sysReserve has already allocated all heap memory,
   160  	// but has not adjusted stats.
   161  	mSysStatInc(sysStat, n)
   162  }
   163  
   164  func sysFault(v unsafe.Pointer, n uintptr) {
   165  }
   166  
   167  func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
   168  	*reserved = true
   169  	lock(&memlock)
   170  	p := memAlloc(n)
   171  	memCheck()
   172  	unlock(&memlock)
   173  	return p
   174  }