1/**
2 * \file
3 * \brief morecore() is a sbrk() equivalent.
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 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 <assert.h>
16#include <k_r_malloc.h>
17#include <stddef.h>
18#include <barrelfish/barrelfish.h>
19#include <barrelfish/core_state.h>
20
21Header *get_malloc_freep(void);
22
23typedef void *(*morecore_alloc_func_t)(size_t bytes, size_t *retbytes);
24typedef void (*morecore_free_func_t)(void *base, size_t bytes);
25
26morecore_alloc_func_t sys_morecore_alloc;
27morecore_free_func_t sys_morecore_free;
28
29/**
30 * \brief sbrk() equivalent.
31 *
32 * This function tries to allocate at least the amount given by 'nu'
33 * in sizeof(::Header) byte units. In some cases, it will allocate
34 * less, if no more memory was available. In any case, It returns a
35 * pointer to the freelist header of the memory region.  NULL is
36 * returned when out of memory.
37 *
38 * \param nu    Number of memory units (1 unit == sizeof(::Header) bytes)
39 *
40 * \return Pointer to freelist header of new memory region or NULL on out of
41 * memory.
42 */
43Header *morecore(unsigned nu)
44{
45    Header *up;
46    size_t nb = nu * sizeof(Header);
47
48    // Allocate requested number of pages and insert freelist header
49    assert(sys_morecore_alloc);
50    up = (Header *)sys_morecore_alloc(nb, &nb);
51    if (up == NULL) {
52        return NULL;
53    }
54    assert(nb % sizeof(Header) == 0);
55    up->s.size = nb / sizeof(Header);
56
57    // Add header to freelist
58    __free_locked((void *)(up + 1));
59    return get_malloc_freep();
60}
61
62/**
63 * \brief sbrk() garbage collector.
64 *
65 * Tries to free up pages at the end of the segment, so to shorten the
66 * segment and return memory to the operating system.
67 */
68void lesscore(void)
69{
70#if defined(__arm__) || defined(__aarch64__)
71    // Not implemented
72
73#else
74    struct morecore_state *state = get_morecore_state();
75    genvaddr_t gvaddr =
76        vregion_get_base_addr(&state->mmu_state.vregion)
77        + state->mmu_state.offset;
78    void *eaddr = (void*)vspace_genvaddr_to_lvaddr(gvaddr);
79
80    assert(sys_morecore_free);
81
82    // Deallocate from end of segment
83    Header *prevp = state->header_freep, *p;
84    for(p = prevp->s.ptr;; prevp = p, p = p->s.ptr) {
85        if(p + p->s.size == eaddr) {
86            prevp->s.ptr = p->s.ptr;
87            state->header_freep = prevp;
88
89            // Give back the memory
90            sys_morecore_free(p, p->s.size * sizeof(Header));
91            break;
92        }
93
94        if (p == state->header_freep) {	/* wrapped around free list */
95            break;
96        }
97    }
98#endif
99}
100