1/* 2 * Copyright (c) 2007, 2008, 2009, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <unistd.h> 11#include <barrelfish/barrelfish.h> 12#include <barrelfish/cpu_arch.h> 13#include <posixcompat.h> // for sbrk_get_*() declarations 14 15// Uncomment this if you want to measure sbrk() collective runtime 16// TODO: make this a Config.hs flag maybe? -SG, 2018-10-18. 17// #define SBRK_COLLECT_STATS 18 19#if __SIZEOF_POINTER__ == 8 20#ifdef __x86_64__ 21// Large memory area + large pages on x86_64 22#define SBRK_REGION_BYTES (128UL * HUGE_PAGE_SIZE) // 64GB 23#define SBRK_FLAGS (VREGION_FLAGS_READ_WRITE | VREGION_FLAGS_LARGE) 24#define SBRK_MIN_MAPPING (16 * LARGE_PAGE_SIZE) 25#define SBRK_REGION_ALIGNMENT LARGE_PAGE_SIZE 26#else 27// Large memory area + normal pages 28#define SBRK_REGION_BYTES (8UL * 512UL * LARGE_PAGE_SIZE) // 8GB 29#define SBRK_FLAGS (VREGION_FLAGS_READ_WRITE) 30#define SBRK_MIN_MAPPING (16 * LARGE_PAGE_SIZE) 31#define SBRK_REGION_ALIGNMENT BASE_PAGE_SIZE 32#endif 33#else 34// still huge, but slightly more achievable in a 32-bit address space! 35#define SBRK_REGION_BYTES (64 * 1024 * BASE_PAGE_SIZE) // 256MB 36#define SBRK_FLAGS (VREGION_FLAGS_READ_WRITE) 37#define SBRK_MIN_MAPPING (2 * BASE_PAGE_SIZE) 38#define SBRK_REGION_ALIGNMENT BASE_PAGE_SIZE 39#endif 40 41 42static void *base = NULL; 43static size_t offset = 0; ///< How much is currently used 44static size_t goffset = 0; ///< Maximum ever allocated 45static struct memobj_append memobj_; 46static struct memobj *memobj = NULL; 47static struct vregion vregion_; 48static struct vregion *vregion = NULL; 49 50struct memobj_anon* sbrk_get_memobj(void) 51{ 52 assert(memobj != NULL); 53 return (struct memobj_anon*) memobj; 54} 55 56struct vregion* sbrk_get_vregion(void) 57{ 58 assert(vregion != NULL); 59 return vregion; 60} 61 62void* sbrk_get_base(void) 63{ 64 assert(base != NULL); 65 return base; 66} 67 68size_t sbrk_get_offset(void) 69{ 70 assert(offset != 0); 71 return offset; 72} 73 74#ifdef SBRK_COLLECT_STATS 75uint64_t sbrk_times = 0; 76 77static inline unsigned long bf_ticks(void) 78{ 79 unsigned int a, d; 80 __asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); 81 return ((unsigned long) a) | (((unsigned long) d) << 32); 82} 83#endif 84 85void *sbrk(intptr_t increment) 86{ 87#ifdef SBRK_COLLECT_STATS 88 uint64_t start = bf_ticks(); 89#endif 90 errval_t err; 91 size_t orig_offset; 92 93 /* we're using an append memobj for sbrk */ 94 if (!memobj) { // Initialize 95 err = vspace_map_append_nomalloc(&base, &memobj_, &vregion_, 96 SBRK_REGION_BYTES, NULL, 97 SBRK_FLAGS, SBRK_REGION_ALIGNMENT); 98 if (err_is_fail(err)) { 99 DEBUG_ERR(err, "vspace_map_anon_nomalloc failed"); 100 return (void *)-1; 101 } 102 memobj = (struct memobj *) &memobj_; 103 vregion = &vregion_; 104 105 //debug_printf("%s:%u reserved region: %p..%p\n", __FUNCTION__, __LINE__, 106 // base, base + SBRK_REGION_BYTES); 107 108 } 109 110 if (increment < 0) { 111 if (-increment > offset) { 112 USER_PANIC("sbrk() called with negative increment beyond offset"); 113 } else { 114 orig_offset = offset; 115 offset += increment; 116 117 void *ret = base + orig_offset; 118 return ret; 119 } 120 } else if (increment == 0) { 121 return base + offset; 122 } else if (offset + increment > SBRK_REGION_BYTES) { 123 debug_printf("sbrk() exceeded static region limit of %zu bytes, offset: %zu\n", 124 (size_t)SBRK_REGION_BYTES, offset); 125 return (void *)-1; 126 } else if (offset + increment <= goffset) { 127 orig_offset = offset; 128 offset += increment; 129 130 void *ret = base + orig_offset; 131 return ret; 132 } 133 134 size_t inc_bytes = offset + increment - goffset; 135 if (inc_bytes < SBRK_MIN_MAPPING) { 136 inc_bytes = SBRK_MIN_MAPPING; 137 } 138 139 140 struct capref frame; 141 err = frame_alloc(&frame, inc_bytes, &inc_bytes); 142 if (err_is_fail(err)) { 143 debug_err(__FILE__, __func__, __LINE__, err, "frame_alloc failed"); 144 return (void *)-1; 145 } 146 147 err = memobj->f.fill(memobj, goffset, frame, 0); 148 if (err_is_fail(err)) { 149 debug_err(__FILE__, __func__, __LINE__, err, "memobj->f.fill failed"); 150 cap_destroy(frame); 151 return (void *)-1; 152 } 153 154 err = memobj->f.pagefault(memobj, vregion, goffset, 0); 155 if (err_is_fail(err)) { 156 debug_err(__FILE__, __func__, __LINE__, err, 157 "memobj->f.pagefault failed"); 158 return (void *)-1; 159 } 160 161 goffset += inc_bytes; 162 163 orig_offset = offset; 164 offset += increment; 165#ifdef SBRK_COLLECT_TIMES 166 uint64_t end = bf_ticks(); 167 sbrk_times += end - start; 168#endif 169 170 void *ret = base + orig_offset; 171 return ret; 172} 173