#include "runtime.h" #include "malloc.h" #include "defs.h" #line 13 "malloc.cgo" MHeap mheap; MStats mstats; #line 19 "malloc.cgo" void* mallocgc ( uintptr size , uint32 refflag , int32 dogc ) { int32 sizeclass; MCache *c; uintptr npages; MSpan *s; void *v; uint32 *ref; #line 29 "malloc.cgo" if ( m->mallocing ) throw ( "malloc/free - deadlock" ) ; m->mallocing = 1; #line 33 "malloc.cgo" if ( size == 0 ) size = 1; #line 36 "malloc.cgo" mstats.nmalloc++; if ( size <= MaxSmallSize ) { #line 39 "malloc.cgo" sizeclass = SizeToClass ( size ) ; size = class_to_size[sizeclass]; c = m->mcache; v = MCache_Alloc ( c , sizeclass , size ) ; if ( v == nil ) throw ( "out of memory" ) ; mstats.alloc += size; } else { #line 50 "malloc.cgo" npages = size >> PageShift; if ( ( size & PageMask ) != 0 ) npages++; s = MHeap_Alloc ( &mheap , npages , 0 ) ; if ( s == nil ) throw ( "out of memory" ) ; mstats.alloc += npages<start << PageShift ) ; } #line 61 "malloc.cgo" if ( !mlookup ( v , nil , nil , &ref ) ) { printf ( "malloc %D; mlookup failed\n" , ( uint64 ) size ) ; throw ( "malloc mlookup" ) ; } *ref = RefNone | refflag; #line 67 "malloc.cgo" m->mallocing = 0; #line 69 "malloc.cgo" if ( dogc && mstats.inuse_pages > mstats.next_gc ) gc ( 0 ) ; return v; } #line 74 "malloc.cgo" void* malloc ( uintptr size ) { return mallocgc ( size , 0 , 0 ) ; } #line 81 "malloc.cgo" void free ( void *v ) { int32 sizeclass , size; uintptr page , tmp; MSpan *s; MCache *c; uint32 *ref; #line 90 "malloc.cgo" if ( v == nil ) return; #line 93 "malloc.cgo" if ( m->mallocing ) throw ( "malloc/free - deadlock" ) ; m->mallocing = 1; #line 97 "malloc.cgo" if ( !mlookup ( v , nil , nil , &ref ) ) throw ( "free mlookup" ) ; *ref = RefFree; #line 102 "malloc.cgo" page = ( uintptr ) v >> PageShift; sizeclass = MHeapMapCache_GET ( &mheap.mapcache , page , tmp ) ; if ( sizeclass == 0 ) { #line 106 "malloc.cgo" s = MHeap_Lookup ( &mheap , page ) ; if ( s == nil ) throw ( "free - invalid pointer" ) ; sizeclass = s->sizeclass; if ( sizeclass == 0 ) { #line 112 "malloc.cgo" mstats.alloc -= s->npages<npages<mcache; size = class_to_size[sizeclass]; runtime_memclr ( v , size ) ; mstats.alloc -= size; MCache_Free ( c , v , sizeclass , size ) ; #line 127 "malloc.cgo" out: m->mallocing = 0; } #line 131 "malloc.cgo" int32 mlookup ( void *v , byte **base , uintptr *size , uint32 **ref ) { uintptr n , nobj , i; byte *p; MSpan *s; #line 138 "malloc.cgo" mstats.nlookup++; s = MHeap_LookupMaybe ( &mheap , ( uintptr ) v>>PageShift ) ; if ( s == nil ) { if ( base ) *base = nil; if ( size ) *size = 0; if ( ref ) *ref = 0; return 0; } #line 150 "malloc.cgo" p = ( byte* ) ( ( uintptr ) s->start<sizeclass == 0 ) { #line 153 "malloc.cgo" if ( base ) *base = p; if ( size ) *size = s->npages<gcref0; return 1; } #line 162 "malloc.cgo" if ( ( byte* ) v >= ( byte* ) s->gcref ) { #line 165 "malloc.cgo" return 0; } #line 168 "malloc.cgo" n = class_to_size[s->sizeclass]; i = ( ( byte* ) v - p ) /n; if ( base ) *base = p + i*n; if ( size ) *size = n; nobj = ( s->npages << PageShift ) / ( n + RefcountOverhead ) ; if ( ( byte* ) s->gcref < p || ( byte* ) ( s->gcref+nobj ) > p+ ( s->npages<state , s , p , s->sizeclass , ( uint64 ) nobj , ( uint64 ) n , ( uint64 ) s->npages ) ; printf ( "s->base sizeclass %d v=%p base=%p gcref=%p blocksize=%D nobj=%D size=%D end=%p end=%p\n" , s->sizeclass , v , p , s->gcref , ( uint64 ) s->npages<gcref + nobj , p+ ( s->npages<gcref[i]; #line 186 "malloc.cgo" return 1; } #line 189 "malloc.cgo" MCache* allocmcache ( void ) { return FixAlloc_Alloc ( &mheap.cachealloc ) ; } #line 195 "malloc.cgo" void mallocinit ( void ) { InitSizes ( ) ; MHeap_Init ( &mheap , SysAlloc ) ; m->mcache = allocmcache ( ) ; #line 203 "malloc.cgo" free ( malloc ( 1 ) ) ; } #line 206 "malloc.cgo" void* SysAlloc ( uintptr n ) { void *p; #line 211 "malloc.cgo" mstats.sys += n; p = runtime_mmap ( nil , n , PROT_READ|PROT_WRITE|PROT_EXEC , MAP_ANON|MAP_PRIVATE , -1 , 0 ) ; if ( p < ( void* ) 4096 ) { if ( p == ( void* ) EACCES ) { printf ( "mmap: access denied\n" ) ; printf ( "If you're running SELinux , enable execmem for this process.\n" ) ; } else { printf ( "mmap: errno=%p\n" , p ) ; } exit ( 2 ) ; } return p; } #line 225 "malloc.cgo" void SysUnused ( void *v , uintptr n ) { USED ( v ) ; USED ( n ) ; #line 231 "malloc.cgo" } #line 233 "malloc.cgo" void SysFree ( void *v , uintptr n ) { USED ( v ) ; USED ( n ) ; #line 239 "malloc.cgo" } #line 243 "malloc.cgo" void* mal ( uint32 n ) { return mallocgc ( n , 0 , 1 ) ; } #line 256 "malloc.cgo" struct { Lock; FixAlloc; } stacks; #line 261 "malloc.cgo" void* stackalloc ( uint32 n ) { void *v; uint32 *ref; #line 267 "malloc.cgo" if ( m->mallocing || m->gcing ) { lock ( &stacks ) ; if ( stacks.size == 0 ) FixAlloc_Init ( &stacks , n , SysAlloc , nil , nil ) ; if ( stacks.size != n ) { printf ( "stackalloc: in malloc , size=%D want %d" , ( uint64 ) stacks.size , n ) ; throw ( "stackalloc" ) ; } v = FixAlloc_Alloc ( &stacks ) ; unlock ( &stacks ) ; return v; } v = malloc ( n ) ; if ( !mlookup ( v , nil , nil , &ref ) ) throw ( "stackalloc mlookup" ) ; *ref = RefStack; return v; } #line 286 "malloc.cgo" void stackfree ( void *v ) { if ( m->mallocing || m->gcing ) { lock ( &stacks ) ; FixAlloc_Free ( &stacks , v ) ; unlock ( &stacks ) ; return; } free ( v ) ; } void malloc·Alloc(uintptr n, byte* p) { #line 298 "malloc.cgo" p = malloc(n); FLUSH(&p); } void malloc·Free(byte* p) { #line 302 "malloc.cgo" free(p); } void malloc·Lookup(byte* p, byte* base, uintptr size) { #line 306 "malloc.cgo" mlookup(p, &base, &size, nil); FLUSH(&base); FLUSH(&size); } void malloc·GetStats(MStats* s) { #line 310 "malloc.cgo" s = &mstats; FLUSH(&s); } void malloc·GC() { #line 314 "malloc.cgo" gc(1); }