9d60b2c610f51a5adc450b90b9ad3cf1436ed19f
[barrelfish] / lib / mm / slot_alloc_2.c
1 /**
2  * \file
3  * \brief Slot management for the memory allocator.
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2016, 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <barrelfish/barrelfish.h>
16 #include <mm/mm.h>
17 #include <mm/slot_alloc.h>
18 #include <stdio.h>
19
20 /// Allocate a new cnode if needed
21 errval_t slot_prealloc_refill_2(struct slot_prealloc_2 *this)
22 {
23     uint8_t refill = !this->current;
24     errval_t err;
25
26     if (this->meta[refill].free == L2_CNODE_SLOTS) {
27         return SYS_ERR_OK; // Nop
28     }
29
30     // Allocate a ram cap
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);
35     }
36
37     // Retype to and build the next cnode
38     struct capref cnode_cap;
39     err = slot_alloc_root(&cnode_cap);
40     if (err_is_fail(err)) {
41         return err_push(err, LIB_ERR_SLOT_ALLOC);
42     }
43
44     err = cnode_create_from_mem(cnode_cap, ram_cap, ObjType_L2CNode,
45             &this->meta[refill].cap.cnode, L2_CNODE_SLOTS);
46     if (err_is_fail(err)) {
47         return err_push(err, LIB_ERR_CNODE_CREATE);
48     }
49
50     // Set the metadata
51     this->meta[refill].cap.slot  = 0;
52     this->meta[refill].free      = L2_CNODE_SLOTS;
53
54     return SYS_ERR_OK;
55 }
56
57 errval_t slot_alloc_prealloc_2(void *inst, uint64_t nslots, struct capref *ret)
58 {
59     struct slot_prealloc_2 *this = inst;
60     assert(nslots <= (1UL << this->maxslotbits));
61
62     /* Check if enough space */
63     if (this->meta[this->current].free < nslots) {
64         // Allocate from next cnode
65         this->current = !this->current;
66     }
67
68     if (this->meta[this->current].free < nslots) {
69         return MM_ERR_SLOT_NOSLOTS;
70     }
71
72     /* Return next slot and update */
73     *ret = this->meta[this->current].cap;
74     this->meta[this->current].cap.slot += nslots;
75     this->meta[this->current].free -= nslots;
76
77     return SYS_ERR_OK;
78 }
79
80 /**
81  * \brief Initialise preallocating slot allocator instance
82  *
83  * \param this Pointer to area for instance data
84  * \param maxslotbits Maximum size of each allocation (in bits)
85  * \param initial_cnode First cap in an empty cnode to start allocating from
86  * \param initial_space Number of slots free in initial cnode
87  * \param ram_mm Memory allocator to use for RAM caps when creating new CNodes
88  */
89 errval_t slot_prealloc_init_2(struct slot_prealloc_2 *this, uint8_t maxslotbits,
90                               struct capref initial_cnode, uint64_t initial_space,
91                               struct mm *ram_mm)
92 {
93     this->maxslotbits = maxslotbits;
94     this->mm = ram_mm;
95
96     //assert(initial_space == (1UL << L2_CNODE_SLOTS));
97     if (initial_space != L2_CNODE_SLOTS &&
98         initial_space != DEFAULT_CNODE_SLOTS) {
99         debug_printf("Initial CNode for 2 level preallocating slot allocator needs to be 16kB");
100         return LIB_ERR_SLOT_ALLOC_INIT;
101     }
102
103     this->current = 0;
104     this->meta[0].cap       = initial_cnode;
105     this->meta[0].free      = initial_space;
106     this->meta[1].free      = 0;
107
108     return SYS_ERR_OK;
109 }