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