| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| #include "runtime.h" | |
| // Stubs for memory management. | |
| // In a separate file so they can be overridden during testing of gc. | |
| enum | |
| { | |
| NHUNK = 20<<20, | |
| PROT_NONE = 0x00, | |
| PROT_READ = 0x01, | |
| PROT_WRITE = 0x02, | |
| PROT_EXEC = 0x04, | |
| MAP_FILE = 0x0000, | |
| MAP_SHARED = 0x0001, | |
| MAP_PRIVATE = 0x0002, | |
| MAP_FIXED = 0x0010, | |
| MAP_ANON = 0x1000, // not on Linux - TODO(rsc) | |
| }; | |
| // Convenient wrapper around mmap. | |
| static void* | |
| brk(uint32 n) | |
| { | |
| byte *v; | |
| v = sys_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0); | |
| m->mem.nmmap += n; | |
| return v; | |
| } | |
| // Allocate n bytes of memory. Note that this gets used | |
| // to allocate new stack segments, so at each call to a function | |
| // you have to ask yourself "would it be okay to call mal recursively | |
| // right here?" The answer is yes unless we're in the middle of | |
| // editing the malloc state in m->mem. | |
| void* | |
| oldmal(uint32 n) | |
| { | |
| byte* v; | |
| // round to keep everything 64-bit aligned | |
| n = rnd(n, 8); | |
| // be careful. calling any function might invoke | |
| // mal to allocate more stack. | |
| if(n > NHUNK) { | |
| v = brk(n); | |
| } else { | |
| // allocate a new hunk if this one is too small | |
| if(n > m->mem.nhunk) { | |
| // here we're in the middle of editing m->mem | |
| // (we're about to overwrite m->mem.hunk), | |
| // so we can't call brk - it might call mal to grow the | |
| // stack, and the recursive call would allocate a new | |
| // hunk, and then once brk returned we'd immediately | |
| // overwrite that hunk with our own. | |
| // (the net result would be a memory leak, not a crash.) | |
| // so we have to call sys_mmap directly - it is written | |
| // in assembly and tagged not to grow the stack. | |
| m->mem.hunk = | |
| sys_mmap(nil, NHUNK, PROT_READ|PROT_WRITE|PROT_EXEC, | |
| MAP_ANON|MAP_PRIVATE, 0, 0); | |
| m->mem.nhunk = NHUNK; | |
| m->mem.nmmap += NHUNK; | |
| } | |
| v = m->mem.hunk; | |
| m->mem.hunk += n; | |
| m->mem.nhunk -= n; | |
| } | |
| m->mem.nmal += n; | |
| return v; | |
| } | |
| void | |
| sys_mal(uint32 n, uint8 *ret) | |
| { | |
| ret = mal(n); | |
| FLUSH(&ret); | |
| } |