-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathz_bmalloc.c
129 lines (79 loc) · 2.19 KB
/
z_bmalloc.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
#include <stdlib.h>
#include <string.h>
#include "m_fixed.h"
#include "z_zone.h"
#include "z_bmalloc.h"
#include "i_system.h"
enum
{
unused_block = 0,
used_block = 1
};
typedef struct bmalpool_s
{
struct bmalpool_s *nextpool;
size_t blocks;
byte used[0];
} bmalpool_t;
inline static void *getelem(bmalpool_t *p, size_t size, size_t n)
{
return (((byte*)p) + sizeof (bmalpool_t) + sizeof (byte) * (p->blocks) + size*n);
}
inline static int iselem(const bmalpool_t *pool, size_t size, const void* p)
{
int dif = (const char*)p - (const char*)pool;
dif -= sizeof(bmalpool_t);
dif -= pool->blocks;
if (dif < 0)
return -1;
dif /= size;
return (((size_t)dif >= pool->blocks) ? -1 : dif);
}
void *Z_BMalloc(struct block_memory_alloc_s *pzone)
{
register bmalpool_t **pool = (bmalpool_t **)&(pzone->firstpool);
bmalpool_t *newpool;
while (*pool != NULL)
{
byte *p = memchr((*pool)->used, unused_block, (*pool)->blocks);
if (p)
{
int n = p - (*pool)->used;
(*pool)->used[n] = used_block;
return getelem(*pool, pzone->size, n);
}
else
{
pool = &((*pool)->nextpool);
}
}
*pool = newpool = Z_Calloc(sizeof(*newpool) + (sizeof(byte) + pzone->size)*(pzone->perpool), 1, pzone->tag, NULL);
newpool->nextpool = NULL;
newpool->used[0] = used_block;
newpool->blocks = pzone->perpool;
return getelem(newpool, pzone->size, 0);
}
void Z_BFree(struct block_memory_alloc_s *pzone, void *p)
{
register bmalpool_t **pool = (bmalpool_t**)&(pzone->firstpool);
while (*pool != NULL)
{
int n = iselem(*pool, pzone->size, p);
if (n >= 0)
{
(*pool)->used[n] = unused_block;
if (memchr(((*pool)->used), used_block, (*pool)->blocks) == NULL)
{
bmalpool_t *oldpool = *pool;
*pool = (*pool)->nextpool;
Z_Free(oldpool);
}
return;
}
else
{
pool = &((*pool)->nextpool);
}
}
I_Error("Z_BFree: Free not in zone %s", pzone->desc);
}