-
Notifications
You must be signed in to change notification settings - Fork 0
/
arena.c
155 lines (123 loc) · 3.59 KB
/
arena.c
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
Copyright (C) 2010-2011, Bruce Ediger
This file is part of acl.
acl is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
acl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with acl; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* $Id: arena.c,v 1.7 2011/07/10 20:10:59 bediger Exp $ */
#include <stdio.h>
#include <unistd.h> /* getpagesize() */
#include <stdlib.h> /* malloc(), free() */
#include <arena.h>
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
union combo {
char c;
short s;
int i;
long l;
long long ll;
void *vp;
char *cp;
short *sp;
int *ip;
long *lp;
float f;
double d;
};
struct memory_arena {
char *first_allocation;
char *next_allocation;
int sz; /* max free size */
int remaining; /* how many bytes remain in allocation */
struct memory_arena *next;
};
static int pagesize = 0;
static int headersize = 0;
static int combosize = 0;
/* Public way to get a new struct memory_arena
* The first struct memory_arena in a chain constitutes a "dummy",
* an empty head element of a FIFO (stack) of structs memory_arena.
* The first allocation demanded from a memory arena will cause
* the malloc() of one or more pages, and a 2nd element in the stack.
*/
struct memory_arena *
new_arena(void)
{
struct memory_arena *ra = NULL;
/* This is not so costly that it can't happen
* on every call to new_arena(). */
combosize = sizeof(union combo);
pagesize = 8 * getpagesize();
headersize = roundup(sizeof(struct memory_arena), combosize);
ra = malloc(sizeof(*ra));
ra->sz = 0;
ra->remaining = 0;
ra->first_allocation = ra->next_allocation = NULL;
ra->next = NULL;
return ra;
}
void
deallocate_arena(struct memory_arena *ma)
{
while (ma)
{
struct memory_arena *tmp = ma->next;
ma->next = NULL;
free(ma);
ma = tmp;
}
}
void
free_arena_contents(struct memory_arena *ma)
{
ma = ma->next; /* dummy head node */
while (ma)
{
ma->remaining = ma->sz;
ma->next_allocation = ma->first_allocation;
ma = ma->next;
}
}
void *
arena_alloc(struct memory_arena *ma, size_t size)
{
void *r = NULL;
struct memory_arena *tmp;
size_t nsize;
/* What you actually have to allocate to get to
* a block "suitably aligned" for any use. */
nsize = roundup(size, combosize);
tmp = ma->next;
while (tmp && nsize > tmp->remaining)
tmp = tmp->next;
if (NULL == tmp)
{
/* You could do something like moving all arenas with
* less than combosize remaining into a 2nd list - one
* that never gets checked, as combosize is the minimum
* allocation possible. */
/* create a new struct memory_arena of at least 1 page */
size_t arena_size = roundup((nsize + headersize), pagesize);
pagesize *= 2; /* make next allocation twice as large */
tmp = malloc(arena_size);
tmp->first_allocation = ((char *)tmp) + headersize;
tmp->next_allocation = tmp->first_allocation;
tmp->sz = arena_size - headersize;
tmp->remaining = tmp->sz;
tmp->next = ma->next;
ma->next = tmp;
}
r = tmp->next_allocation;
tmp->next_allocation += nsize; /* next_allocation stays aligned */
tmp->remaining -= nsize;
return r;
}