mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-14 17:01:22 +00:00
218 lines
6 KiB
C
218 lines
6 KiB
C
|
#define PARANOID
|
||
|
#include "../zone.c"
|
||
|
|
||
|
static int
|
||
|
check_hunk_block (const memhunk_t *hunk, const void *mem, size_t size)
|
||
|
{
|
||
|
const hunkblk_t *h = (const hunkblk_t *) mem - 1;
|
||
|
if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) {
|
||
|
printf ("invalid sentinals: %u %u\n", h->sentinal1, h->sentinal2);
|
||
|
return 1;
|
||
|
}
|
||
|
if (h->size % HUNK_ALIGN) {
|
||
|
printf ("block size misaligned: %zd %zd\n",
|
||
|
h->size, h->size % HUNK_ALIGN);
|
||
|
return 1;
|
||
|
}
|
||
|
if (h->size - sizeof (hunkblk_t) < size) {
|
||
|
printf ("block size too small: %zd %zd\n",
|
||
|
h->size - sizeof (hunkblk_t), size);
|
||
|
return 1;
|
||
|
}
|
||
|
if (h->size - sizeof (hunkblk_t) - size >= HUNK_ALIGN) {
|
||
|
printf ("block size too small: %zd %d\n",
|
||
|
h->size - sizeof (hunkblk_t) - size, HUNK_ALIGN);
|
||
|
return 1;
|
||
|
}
|
||
|
if ((byte *) h < hunk->base
|
||
|
|| (byte *) h + h->size > hunk->base + hunk->size) {
|
||
|
printf ("block outside of hunk: %p %p, %p %p\n",
|
||
|
h, hunk->base, (byte *) h + h->size, hunk->base + hunk->size);
|
||
|
return 1;
|
||
|
}
|
||
|
size_t offset = (byte *) h - hunk->base;
|
||
|
if (offset < hunk->size - hunk->high_used
|
||
|
&& offset + h->size > hunk->low_used) {
|
||
|
printf ("block in unallocated region: %zd %zd, %zd %zd\n",
|
||
|
offset, offset + h->size,
|
||
|
hunk->low_used, hunk->size - hunk->high_used);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
check_cache_block (const memhunk_t *hunk, const void *c, size_t size)
|
||
|
{
|
||
|
if (!c) {
|
||
|
printf ("cache block is null\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
const cache_system_t *cs = (cache_system_t *) c - 1;
|
||
|
|
||
|
size_t hunk_high = hunk->size - hunk->high_used;
|
||
|
size_t offset = (byte *) cs - hunk->base;
|
||
|
if (offset < hunk->low_used || offset + cs->size > hunk_high) {
|
||
|
printf ("cache block in hunk stack: %zd %zd, %zd, %zd\n",
|
||
|
offset, offset + cs->size, hunk->low_used, hunk_high);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
check_cache_order (memhunk_t *hunk)
|
||
|
{
|
||
|
uint32_t ci;
|
||
|
cache_system_t *c;
|
||
|
int ret = 0;
|
||
|
|
||
|
cache_system_t *first = cs_ptr (hunk, hunk->cache_head[0].next);
|
||
|
cache_system_t *last = cs_ptr (hunk, hunk->cache_head[0].prev);
|
||
|
|
||
|
if (first->prev) {
|
||
|
printf ("first cache block does not point back to head: %u\n",
|
||
|
first->prev);
|
||
|
}
|
||
|
if (last->next) {
|
||
|
printf ("last cache block does not point forward to head: %u\n",
|
||
|
last->next);
|
||
|
}
|
||
|
if (first->prev || last->next) {
|
||
|
exit (1); // unsafe to continue
|
||
|
}
|
||
|
uint32_t prev = 0;
|
||
|
for (ci = hunk->cache_head[0].next; ci; prev = ci, ci = c->next) {
|
||
|
c = cs_ptr (hunk, ci);
|
||
|
if ((byte *) c + c->size > hunk->base + hunk->size) {
|
||
|
printf ("cache block outside of hunk (from %u)\n", prev);
|
||
|
exit (1);
|
||
|
}
|
||
|
if (c->readlock) {
|
||
|
printf ("look in cache detected at %u\n", ci);
|
||
|
exit (1);
|
||
|
}
|
||
|
c->readlock = 1;
|
||
|
if (c->next && c->next < ci) {
|
||
|
printf ("cache block sequence incorrect %u -> %u\n", prev, ci);
|
||
|
ret |= 1;
|
||
|
}
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main (int argc, const char **argv)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
|
||
|
if (sizeof (memhunk_t) != 128) {
|
||
|
ret = 1;
|
||
|
printf ("memhunk_t not 128 bytes: %zd\n", sizeof (memhunk_t));
|
||
|
}
|
||
|
if (sizeof (hunkblk_t) != 64) {
|
||
|
ret = 1;
|
||
|
printf ("hunkblk_t not 64 bytes: %zd\n", sizeof (memhunk_t));
|
||
|
}
|
||
|
size_t memsize = 64 * 1024;
|
||
|
void *hunk_mem = Sys_Alloc (memsize);
|
||
|
if ((intptr_t) hunk_mem & 63) {
|
||
|
// (not really part of test, but relied upon) should be 4k
|
||
|
// aligned, but doesn't matter for the tests
|
||
|
printf ("Sys_Alloc returned unaligned memory");
|
||
|
ret = 1;
|
||
|
}
|
||
|
memhunk_t *hunk = Hunk_Init (hunk_mem, memsize);
|
||
|
if ((void *) hunk != hunk_mem) {
|
||
|
ret = 1;
|
||
|
printf ("hunk moved\n");
|
||
|
}
|
||
|
if ((void *) hunk->base != (void *)&hunk[1]) {
|
||
|
ret = 1;
|
||
|
printf ("hunk->base does not point to beginning of hunk space\n");
|
||
|
}
|
||
|
if (hunk->size != memsize - sizeof (memhunk_t)) {
|
||
|
ret = 1;
|
||
|
printf ("hunk size not memsize - sizeof (memhunk_t) (%zd - %zd): %zd\n",
|
||
|
memsize, sizeof (memhunk_t), hunk->size);
|
||
|
}
|
||
|
if (hunk->low_used || hunk->high_used) {
|
||
|
ret = 1;
|
||
|
printf ("hunk low and high used not 0: %zd %zd\n",
|
||
|
hunk->low_used, hunk->high_used);
|
||
|
}
|
||
|
if (hunk->tempmark || hunk->tempactive) {
|
||
|
ret = 1;
|
||
|
printf ("hunk tempmark tempactive not 0: %zd %d\n",
|
||
|
hunk->tempmark, hunk->tempactive);
|
||
|
}
|
||
|
if (ret) {
|
||
|
// no point continuing
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
size_t low_mark = Hunk_LowMark (hunk);
|
||
|
if (low_mark != 0) {
|
||
|
ret = 1;
|
||
|
printf ("initial hunk low mark not 0: %zd\n", low_mark);
|
||
|
}
|
||
|
size_t size = 1024;
|
||
|
void *low = Hunk_AllocName (hunk, size, "low test");
|
||
|
ret |= check_hunk_block (hunk, low, size);
|
||
|
if (low > (void *) (hunk->base + sizeof (hunkblk_t))) {
|
||
|
ret = 1;
|
||
|
printf ("low memory not at beginning of hunk: %p %p\n",
|
||
|
low, hunk->base + sizeof (hunkblk_t));
|
||
|
}
|
||
|
|
||
|
size_t high_mark = Hunk_HighMark (hunk);
|
||
|
if (high_mark != 0) {
|
||
|
ret = 1;
|
||
|
printf ("initial hunk high mark not 0: %zd\n", high_mark);
|
||
|
}
|
||
|
void *high = Hunk_HighAlloc (hunk, size);//FIXME, "high test");
|
||
|
ret |= check_hunk_block (hunk, high, size);
|
||
|
if (high + size < (void *) (hunk->base + hunk->size)) {
|
||
|
ret = 1;
|
||
|
printf ("high memory not at end of hunk: %p %p\n",
|
||
|
high + size, hunk->base + hunk->size);
|
||
|
}
|
||
|
|
||
|
global_hunk = hunk;//FIXME put hunk in cache_user_t ?
|
||
|
cache_user_t cu = {};
|
||
|
void *cm = Cache_Alloc (&cu, 512, "cache test");
|
||
|
ret |= check_cache_block (hunk, cm, 512);
|
||
|
|
||
|
size_t mark = Hunk_LowMark (hunk);
|
||
|
void *low2 = Hunk_AllocName (hunk, 61 * 1024, "low test 2");
|
||
|
ret |= check_hunk_block (hunk, low2, 61 * 1024);
|
||
|
if (cm == Cache_Check (&cu)) {
|
||
|
ret = 1;
|
||
|
printf ("cache block was not moved\n");
|
||
|
}
|
||
|
cm = Cache_Check (&cu);
|
||
|
ret |= check_cache_block (hunk, cm, 512);
|
||
|
Hunk_FreeToLowMark (hunk, mark);
|
||
|
if (cm != Cache_Check (&cu)) {
|
||
|
ret = 1;
|
||
|
printf ("cache block was moved\n");
|
||
|
}
|
||
|
|
||
|
void *high2 = Hunk_HighAlloc (hunk, 2 * 1024);
|
||
|
ret |= check_hunk_block (hunk, high2, 2 * 1024);
|
||
|
if (cm == Cache_Check (&cu)) {
|
||
|
ret = 1;
|
||
|
printf ("cache block was not moved\n");
|
||
|
}
|
||
|
cm = Cache_Check (&cu);
|
||
|
ret |= check_cache_block (hunk, cm, 512);
|
||
|
printf ("%zd %zd %zd\n", hunk->low_used, hunk->size - hunk->high_used,
|
||
|
(byte *) cm - hunk->base);
|
||
|
check_cache_order (hunk);
|
||
|
Hunk_Print(hunk, 1);
|
||
|
Cache_Print ();
|
||
|
|
||
|
return ret;
|
||
|
}
|