3 * \brief Slot management for the memory allocator.
7 * Copyright (c) 2007, 2008, 2016, ETH Zurich.
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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
15 #include <barrelfish/barrelfish.h>
17 #include <mm/slot_alloc.h>
20 /// Allocate a new cnode if needed
21 errval_t slot_prealloc_refill_2(struct slot_prealloc_2 *this)
23 uint8_t refill = !this->current;
26 if (this->meta[refill].free == L2_CNODE_SLOTS) {
27 return SYS_ERR_OK; // Nop
31 struct capref ram_cap;
32 err = mm_alloc(this->mm, L2_CNODE_BITS + OBJBITS_CTE, &ram_cap, NULL);
33 if (err_is_fail(err)) {
34 return err_push(err, MM_ERR_SLOT_MM_ALLOC);
37 // Retype to and build the next cnode
38 struct capref cnode_cap;
39 err = slot_alloc_root(&cnode_cap);
40 if (err_no(err) == LIB_ERR_SLOT_ALLOC_NO_SPACE) {
41 // Root cnode full, resize it
42 uint8_t rootbits = log2ceil(this->rootcn_slots);
43 assert((1UL << rootbits) == this->rootcn_slots);
45 struct capref root_ram, newroot_cap;
46 err = mm_alloc(this->mm, rootbits + 1 + OBJBITS_CTE, &root_ram, NULL);
47 if (err_is_fail(err)) {
48 return err_push(err, MM_ERR_SLOT_MM_ALLOC);
50 err = slot_alloc(&newroot_cap);
51 if (err_is_fail(err)) {
52 return err_push(err, LIB_ERR_SLOT_ALLOC);
54 err = cnode_create_from_mem(newroot_cap, root_ram, ObjType_L1CNode,
55 NULL, this->rootcn_slots * 2);
56 if (err_is_fail(err)) {
57 return err_push(err, LIB_ERR_CNODE_CREATE_FROM_MEM);
59 // Delete RAM cap of new CNode
60 err = cap_delete(root_ram);
61 if (err_is_fail(err)) {
62 return err_push(err, LIB_ERR_CAP_DELETE);
66 debug_printf("retslot: %"PRIxCADDR"\n", get_cap_addr(root_ram));
67 err = root_cnode_resize(newroot_cap, root_ram);
68 if (err_is_fail(err)) {
69 DEBUG_ERR(err, "resizing root cnode");
73 // Delete old Root CNode and free slot
74 err = cap_destroy(root_ram);
75 if (err_is_fail(err)) {
76 DEBUG_ERR(err, "deleting old root cnode");
77 return err_push(err, LIB_ERR_CAP_DESTROY);
80 // update root slot allocator size and our metadata
81 rootsa_update(this->rootcn_slots *= 2);
83 // retry slot_alloc_root
84 err = slot_alloc_root(&cnode_cap);
86 if (err_is_fail(err)) {
87 return err_push(err, LIB_ERR_SLOT_ALLOC);
90 err = cnode_create_from_mem(cnode_cap, ram_cap, ObjType_L2CNode,
91 &this->meta[refill].cap.cnode, L2_CNODE_SLOTS);
92 if (err_is_fail(err)) {
93 return err_push(err, LIB_ERR_CNODE_CREATE);
97 this->meta[refill].cap.slot = 0;
98 this->meta[refill].free = L2_CNODE_SLOTS;
103 errval_t slot_alloc_prealloc_2(void *inst, uint64_t nslots, struct capref *ret)
105 struct slot_prealloc_2 *this = inst;
106 assert(nslots <= (1UL << this->maxslotbits));
108 /* Check if enough space */
109 if (this->meta[this->current].free < nslots) {
110 // Allocate from next cnode
111 this->current = !this->current;
114 if (this->meta[this->current].free < nslots) {
115 return MM_ERR_SLOT_NOSLOTS;
118 /* Return next slot and update */
119 *ret = this->meta[this->current].cap;
120 this->meta[this->current].cap.slot += nslots;
121 this->meta[this->current].free -= nslots;
127 * \brief Initialise preallocating slot allocator instance
129 * \param this Pointer to area for instance data
130 * \param maxslotbits Maximum size of each allocation (in bits)
131 * \param initial_cnode First cap in an empty cnode to start allocating from
132 * \param initial_space Number of slots free in initial cnode
133 * \param ram_mm Memory allocator to use for RAM caps when creating new CNodes
135 errval_t slot_prealloc_init_2(struct slot_prealloc_2 *this, uint8_t maxslotbits,
136 struct capref initial_cnode, uint64_t initial_space,
139 this->maxslotbits = maxslotbits;
142 assert(initial_space == L2_CNODE_SLOTS);
143 if (initial_space != L2_CNODE_SLOTS) {
144 debug_printf("Initial CNode for 2 level preallocating slot allocator needs to be 16kB");
145 return LIB_ERR_SLOT_ALLOC_INIT;
149 this->meta[0].cap = initial_cnode;
150 this->meta[0].free = initial_space;
151 this->meta[1].free = 0;
153 // XXX: Do something like
154 // this->rootcn_slots = invoke_cnode_get_slots(cap_root);
155 this->rootcn_slots = L2_CNODE_SLOTS;