1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/*
Buddy allocator
Copyright (c) 2021 Aron Barath
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Author nor the names of contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Source code: svn://svn.repo.hu/libualloc/trunk
Contact the author: aron-dev@mailbox.org
*/
#ifndef BUDDY_H
#define BUDDY_H
#include <stdlib.h>
#include <libualloc/libualloc.h>
/* Can be redefined by the caller to make addresses smaller */
#ifndef UALL_BUDDY_ADDR_T
# define UALL_BUDDY_ADDR_T size_t
#endif
typedef UALL_BUDDY_ADDR_T uall_buddy_addr_t;
typedef uall_buddy_addr_t uall_buddy_size_t;
typedef uall_buddy_addr_t buddy_segm_t;
typedef unsigned char uall_buddy_byte_t;
typedef struct uall_bchunk_s {
uall_buddy_addr_t next;
uall_buddy_addr_t prev;
} uall_bchunk_t;
typedef struct aull_buddy1_s uall_buddy1_t;
struct aull_buddy1_s {
uall_buddy1_t *next; /* next buddy allocator (only used in "uall" mode) */
uall_buddy_addr_t memory; /* base address of the allocatable memory */
uall_buddy_addr_t chunks_info;/* size and reservation information about chunks */
uall_buddy_size_t total_size; /* total size of the allocatable memory (will not changed) */
uall_buddy_size_t act_max_size; /* maximal size of the actually allocatable chunk */
uall_buddy_size_t min_size; /* minimal possible chunk size to allocate */
uall_buddy_size_t num_minchunks; /* total number of min-sized chunk (size of the chunks_info) */
uall_buddy_byte_t min_bits; /* log2 of min_size */
uall_buddy_byte_t num_levels; /* total number of levels */
uall_buddy_byte_t max_bits; /* power of the largest block */
uall_buddy_byte_t padding; /* (really, just padding) */
uall_bchunk_t chunk_lists[1]; /* list of free chunks */
};
/* this is the core buddy allocator -- the whole state can be copied */
UALL_INLINE uall_buddy1_t *uall_buddy_init_(uall_buddy1_t *const buddy, uall_buddy_size_t size, uall_buddy_size_t minsize);
UALL_INLINE uall_buddy_addr_t uall_buddy_alloc_(uall_buddy1_t *const buddy, uall_buddy_size_t size);
UALL_INLINE void uall_buddy_free_(uall_buddy1_t *const buddy, uall_buddy_addr_t block);
UALL_INLINE uall_buddy_size_t uall_buddy_msize(uall_buddy1_t *const buddy, uall_buddy_addr_t block);
/* Convert a global pointer (void*) to a local address (uall_buddy_addr_t).
This macro works only if the global pointer is the member of the given
buddy allocator base. */
#define uall_buddy_gp2la(_base_, _global_pointer_) \
((uall_buddy_addr_t)( \
((uall_buddy_byte_t*)(_global_pointer_)) - ((uall_buddy_byte_t*)(_base_)) \
))
/* Converts a local address (uall_buddy_addr_t) to a global pointer (void*).
Same restrictions apply as to uall_buddy_gp2la(). */
#define uall_buddy_la2gp(_base_, _local_address_) \
((void*)( \
((uall_buddy_byte_t*)(_base_)) + ((uall_buddy_addr_t)(_local_address_)) \
))
typedef struct uall_buddy_s {
/*** user configuration and callbacks ***/
uall_sysalloc_t *sys;
void *user_handle; /* optional: can be used by caller supplied ->grow() to keep track of allocation handle */
size_t user_size; /* optional: can be used by caller supplied ->grow() to keep track of allocation size */
void *user_data; /* arbitrary data set by the caller */
/*** internal state ***/
uall_buddy1_t *_first;
uall_buddy1_t *_last;
buddy_segm_t _nsegments;
size_t _maxsize;
} uall_buddy_t;
typedef struct uall_buddy_va_s {
buddy_segm_t segm;
uall_buddy_addr_t addr;
} uall_buddy_va_t;
void uall_buddy_init(uall_buddy_t *ctx);
/* restore a previously exported segment -- in fact, this is just appends
to the list of known buddy allocator cores */
UALL_INLINE void uall_buddy_restore_segment(uall_buddy_t *ctx, void *base);
UALL_INLINE void *uall_buddy_alloc(uall_buddy_t *ctx, size_t size);
UALL_INLINE void uall_buddy_free(uall_buddy_t *ctx, void *ptr);
/* returns zero on success */
UALL_INLINE int uall_buddy_alloc_va(uall_buddy_t *ctx, size_t size, uall_buddy_va_t *const va);
UALL_INLINE int uall_buddy_free_va(uall_buddy_t *ctx, uall_buddy_va_t *const va);
UALL_INLINE void *uall_buddy_va2ptr(uall_buddy_t *ctx, const uall_buddy_va_t *const va);
UALL_INLINE int uall_buddy_ptr2va(uall_buddy_t *ctx, uall_buddy_va_t *const va, void *ptr);
#define UALL_BUDDY_RESERVED_BIT 0x80
#define UALL_BUDDY_LEVELS_MASK 0x7f
#endif /* BUDDY_H */
|