1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * This is designed to be a fast allocator for small, regularly used block sizes
29 *-----------------------------------------------------------------------------
33 #include "z_bmalloc.h"
35 #include "rockmacros.h"
37 typedef struct bmalpool_s
{
38 struct bmalpool_s
*nextpool
;
43 inline static void* getelem(bmalpool_t
*p
, size_t size
, size_t n
)
45 return (((byte
*)p
) + sizeof(bmalpool_t
) + sizeof(byte
)*(p
->blocks
) + size
*n
);
48 inline static int iselem(const bmalpool_t
*pool
, size_t size
, const void* p
)
50 // CPhipps - need portable # of bytes between pointers
51 int dif
= (const char*)p
- (const char*)pool
;
53 dif
-= sizeof(bmalpool_t
);
57 return (((size_t)dif
>= pool
->blocks
) ? -1 : dif
);
60 enum { unused_block
= 0, used_block
= 1};
62 void* Z_BMalloc(struct block_memory_alloc_s
*pzone
)
64 register bmalpool_t
**pool
= (bmalpool_t
**)&(pzone
->firstpool
);
65 while (*pool
!= NULL
) {
66 byte
*p
= memchr((*pool
)->used
, unused_block
, (*pool
)->blocks
); // Scan for unused marker
68 int n
= p
- (*pool
)->used
;
70 if ((n
<0) || ((size_t)n
>=(*pool
)->blocks
))
71 I_Error("Z_BMalloc: memchr returned pointer outside of array");
73 (*pool
)->used
[n
] = used_block
;
74 return getelem(*pool
, pzone
->size
, n
);
76 pool
= &((*pool
)->nextpool
);
79 // Nothing available, must allocate a new pool
82 // CPhipps: Allocate new memory, initialised to 0
84 *pool
= newpool
= Z_Calloc(sizeof(*newpool
) + (sizeof(byte
) + pzone
->size
)*(pzone
->perpool
),
86 newpool
->nextpool
= NULL
; // NULL = (void*)0 so this is redundant
88 // Return element 0 from this pool to satisfy the request
89 newpool
->used
[0] = used_block
;
90 newpool
->blocks
= pzone
->perpool
;
91 return getelem(newpool
, pzone
->size
, 0);
95 void Z_BFree(struct block_memory_alloc_s
*pzone
, void* p
)
97 register bmalpool_t
**pool
= (bmalpool_t
**)&(pzone
->firstpool
);
99 while (*pool
!= NULL
) {
100 int n
= iselem(*pool
, pzone
->size
, p
);
103 if ((*pool
)->used
[n
] == unused_block
)
104 I_Error("Z_BFree: Refree in zone %s", pzone
->desc
);
106 (*pool
)->used
[n
] = unused_block
;
107 if (memchr(((*pool
)->used
), used_block
, (*pool
)->blocks
) == NULL
) {
108 // Block is all unused, can be freed
109 bmalpool_t
*oldpool
= *pool
;
110 *pool
= (*pool
)->nextpool
;
114 } else pool
= &((*pool
)->nextpool
);
116 I_Error("Z_BFree: Free not in zone %s", pzone
->desc
);