Initial version of public stable barrelfish repository.
[barrelfish] / lib / barrelfish / morecore.c
1 /**
2  * \file
3  * \brief Morecore implementation for malloc
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <barrelfish/barrelfish.h>
16 #include <barrelfish/core_state.h>
17 #include <barrelfish/morecore.h>
18 #include <stdio.h>
19
20 /// Amount of virtual space for malloc
21 #ifdef __x86_64__
22 #       define HEAP_REGION (2UL * 1024 * 1024 * 1024) /* 2GB */
23 #elif defined(__i386__) || defined(__arm__) || defined(__BEEHIVE__)
24 #       define HEAP_REGION (512UL * 1024 * 1024) /* 512MB */
25 #else
26 #       error "HEAP_REGION needs to be defined for this system."
27 #endif
28
29 typedef void *(*morecore_alloc_func_t)(size_t bytes, size_t *retbytes);
30 extern morecore_alloc_func_t sys_morecore_alloc;
31
32 typedef void (*morecore_free_func_t)(void *base, size_t bytes);
33 extern morecore_free_func_t sys_morecore_free;
34
35 /**
36  * \brief Allocate some memory for malloc to use
37  *
38  * This function will keep trying with smaller and smaller frames till
39  * it finds a set of frames that satisfy the requirement. retbytes
40  * will be >= bytes.
41  */
42 static void *morecore_alloc(size_t bytes, size_t *retbytes)
43 {
44     errval_t err;
45     struct morecore_state *state = get_morecore_state();
46
47     void *buf = NULL;
48     size_t mapped = 0;
49     size_t step = bytes;
50     while (mapped < bytes) {
51         struct capref cap;
52         err = slot_alloc(&cap);
53         if (err_is_fail(err)) {
54             USER_PANIC_ERR(err, "slot_alloc failed");
55         }
56
57         void *mid_buf = NULL;
58         err = vspace_mmu_aware_map(&state->mmu_state, cap, step,
59                                    &mid_buf, &step);
60         if (err_is_ok(err)) {
61             if (buf == NULL) {
62                 buf = mid_buf;
63             }
64             mapped += step;
65         } else {
66             /*
67               vspace_mmu_aware_map failed probably because we asked
68               for a very large frame, will try asking for smaller one.
69              */
70             if (err_no(err) == LIB_ERR_FRAME_CREATE_MS_CONSTRAINTS) {
71                 err = slot_free(cap);
72                 if (err_is_fail(err)) {
73                     debug_err(__FILE__, __func__, __LINE__, err,
74                               "slot_free failed");
75                     return NULL;
76                 }
77                 if (step < BASE_PAGE_SIZE) {
78                     debug_err(__FILE__, __func__, __LINE__, err,
79                               "vspace_mmu_aware_map fail (out of memory?)");
80                     return NULL;
81                 }
82                 step /= 2;
83                 continue;
84             } else {
85                 debug_err(__FILE__, __func__, __LINE__, err,
86                           "vspace_mmu_aware_map fail");
87                 return NULL;
88             }
89         }
90     }
91
92     *retbytes = mapped;
93     return buf;
94 }
95
96 static void morecore_free(void *base, size_t bytes)
97 {
98     struct morecore_state *state = get_morecore_state();
99     errval_t err = vspace_mmu_aware_unmap(&state->mmu_state,
100                                           (lvaddr_t)base, bytes);
101     if(err_is_fail(err)) {
102         USER_PANIC_ERR(err, "vspace_mmu_aware_unmap");
103     }
104 }
105
106 Header *get_malloc_freep(void);
107 Header *get_malloc_freep(void)
108 {
109     return get_morecore_state()->header_freep;
110 }
111
112 errval_t morecore_init(void)
113 {
114     errval_t err;
115     struct morecore_state *state = get_morecore_state();
116
117     thread_mutex_init(&state->mutex);
118
119     err = vspace_mmu_aware_init(&state->mmu_state, HEAP_REGION);
120     if (err_is_fail(err)) {
121         return err_push(err, LIB_ERR_VSPACE_MMU_AWARE_INIT);
122     }
123
124     sys_morecore_alloc = morecore_alloc;
125     sys_morecore_free = morecore_free;
126
127     return SYS_ERR_OK;
128 }