main
arena.c
1/*
2 Copyright 2015 Michael Pavone
3 This file is part of BlastEm.
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
5*/
6#include <stdlib.h>
7#include <stdint.h>
8#include "arena.h"
9
10struct arena {
11 void **used_blocks;
12 void **free_blocks;
13
14 size_t used_count;
15 size_t used_storage;
16 size_t free_count;
17 size_t free_storage;
18};
19
20#define DEFAULT_STORAGE_SIZE 8
21
22static arena *current_arena;
23
24arena *get_current_arena()
25{
26 if (!current_arena) {
27 current_arena = calloc(1, sizeof(arena));
28 }
29 return current_arena;
30}
31
32arena *set_current_arena(arena *a)
33{
34 arena *tmp = current_arena;
35 current_arena = a;
36 return tmp;
37}
38
39arena *start_new_arena()
40{
41 arena *tmp = current_arena;
42 current_arena = NULL;
43 return tmp;
44}
45
46void track_block(void *block)
47{
48 arena *cur = get_current_arena();
49 if (cur->used_count == cur->used_storage) {
50 if (cur->used_storage) {
51 cur->used_storage *= 2;
52 } else {
53 cur->used_storage = DEFAULT_STORAGE_SIZE;
54 }
55 cur->used_blocks = realloc(cur->used_blocks, cur->used_storage * sizeof(void *));
56 }
57 cur->used_blocks[cur->used_count++] = block;
58}
59
60void mark_all_free()
61{
62 arena *cur = get_current_arena();
63 if (!cur->free_blocks) {
64 cur->free_blocks = cur->used_blocks;
65 cur->free_storage = cur->used_storage;
66 cur->free_count = cur->used_count;
67 cur->used_count = cur->used_storage = 0;
68 cur->used_blocks = NULL;
69 } else {
70 if (cur->free_storage < cur->used_count + cur->free_count) {
71 cur->free_storage = cur->used_count + cur->free_count;
72 cur->free_blocks = realloc(cur->free_blocks, cur->free_storage * sizeof(void*));
73 }
74 for (; cur->used_count > 0; cur->used_count--)
75 {
76 cur->free_blocks[cur->free_count++] = cur->used_blocks[cur->used_count-1];
77 }
78 }
79}
80
81void *try_alloc_arena()
82{
83 if (!current_arena || !current_arena->free_count) {
84 return NULL;
85 }
86 void *ret = current_arena->free_blocks[--current_arena->free_count];
87 track_block(ret);
88 return ret;
89}