Fix allocator routines. Instead of abusing CIRCLEQ pointers, add an explicit

type field to tag memory nodes that are or are not on the free list.
This commit is contained in:
mlelstv 2014-01-03 07:14:20 +00:00
parent 795bcb0d40
commit aafa26eec9
4 changed files with 45 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cc.c,v 1.24 2013/11/27 17:24:43 christos Exp $ */
/* $NetBSD: cc.c,v 1.25 2014/01/03 07:14:20 mlelstv Exp $ */
/*
* Copyright (c) 1994 Christian E. Hopps
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cc.c,v 1.24 2013/11/27 17:24:43 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: cc.c,v 1.25 2014/01/03 07:14:20 mlelstv Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -513,7 +513,7 @@ alloc_chipmem(u_long size)
* for a new node in between.
*/
TAILQ_REMOVE(&free_list, mn, free_link);
TAILQ_NEXT(mn, free_link) = NULL;
mn->type = MNODE_USED;
size = mn->size; /* increase size. (or same) */
chip_total -= mn->size;
splx(s);
@ -533,7 +533,7 @@ alloc_chipmem(u_long size)
* and mark as not on free list
*/
TAILQ_INSERT_AFTER(&chip_list, new, mn, link);
TAILQ_NEXT(mn, free_link) = NULL;
mn->type = MNODE_USED;
chip_total -= size + sizeof(struct mem_node);
splx(s);
@ -557,52 +557,53 @@ free_chipmem(void *mem)
/*
* check ahead of us.
*/
if (TAILQ_NEXT(next, link) != NULL &&
TAILQ_NEXT(next, free_link) != NULL) {
if (next->type == MNODE_FREE) {
/*
* if next is: a valid node and a free node. ==> merge
*/
TAILQ_INSERT_BEFORE(next, mn, free_link);
mn->type = MNODE_FREE;
TAILQ_REMOVE(&chip_list, next, link);
TAILQ_REMOVE(&chip_list, next, free_link);
TAILQ_REMOVE(&free_list, next, free_link);
chip_total += mn->size + sizeof(struct mem_node);
mn->size += next->size + sizeof(struct mem_node);
}
if (TAILQ_PREV(prev, chiplist, link) != NULL &&
TAILQ_PREV(prev, freelist, free_link) != NULL) {
if (prev->type == MNODE_FREE) {
/*
* if prev is: a valid node and a free node. ==> merge
*/
if (TAILQ_NEXT(mn, free_link) == NULL)
if (mn->type != MNODE_FREE)
chip_total += mn->size + sizeof(struct mem_node);
else {
/* already on free list */
TAILQ_REMOVE(&free_list, mn, free_link);
mn->type = MNODE_USED;
chip_total += sizeof(struct mem_node);
}
TAILQ_REMOVE(&chip_list, mn, link);
prev->size += mn->size + sizeof(struct mem_node);
} else if (TAILQ_NEXT(mn, free_link) == NULL) {
} else if (mn->type != MNODE_FREE) {
/*
* we still are not on free list and we need to be.
* <-- | -->
*/
while (TAILQ_NEXT(next, link) != NULL &&
TAILQ_PREV(prev, chiplist, link) != NULL) {
if (TAILQ_NEXT(next, free_link) != NULL) {
while (next != NULL && prev != NULL) {
if (next->type == MNODE_FREE) {
TAILQ_INSERT_BEFORE(next, mn, free_link);
mn->type = MNODE_FREE;
break;
}
if (TAILQ_NEXT(prev, free_link) != NULL) {
if (prev->type == MNODE_FREE) {
TAILQ_INSERT_AFTER(&free_list, prev, mn,
free_link);
mn->type = MNODE_FREE;
break;
}
prev = TAILQ_PREV(prev, chiplist, link);
next = TAILQ_NEXT(next, link);
}
if (TAILQ_NEXT(mn, free_link) == NULL) {
if (TAILQ_NEXT(next, link) == NULL) {
if (mn->type != MNODE_FREE) {
if (next == NULL) {
/*
* we are not on list so we can add
* ourselves to the tail. (we walked to it.)
@ -611,6 +612,7 @@ free_chipmem(void *mem)
} else {
TAILQ_INSERT_HEAD(&free_list,mn,free_link);
}
mn->type = MNODE_FREE;
}
chip_total += mn->size; /* add our helpings to the pool. */
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cc.h,v 1.17 2013/11/23 22:48:00 christos Exp $ */
/* $NetBSD: cc.h,v 1.18 2014/01/03 07:14:20 mlelstv Exp $ */
/*
* Copyright (c) 1994 Christian E. Hopps
@ -160,7 +160,10 @@ struct mem_node {
TAILQ_ENTRY(mem_node) link;
TAILQ_ENTRY(mem_node) free_link;
u_long size; /* size of memory following node. */
u_char type; /* free, used */
};
#define MNODE_FREE 0
#define MNODE_USED 1
#define CM_BLOCKSIZE 0x4
#define CM_BLOCKMASK (~(CM_BLOCKSIZE - 1))

View File

@ -1,4 +1,4 @@
/* $NetBSD: stalloc.c,v 1.15 2013/11/27 17:24:43 christos Exp $ */
/* $NetBSD: stalloc.c,v 1.16 2014/01/03 07:14:20 mlelstv Exp $ */
/*
* Copyright (c) 1995 Leo Weppelman (Atari modifications)
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: stalloc.c,v 1.15 2013/11/27 17:24:43 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: stalloc.c,v 1.16 2014/01/03 07:14:20 mlelstv Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -117,7 +117,7 @@ alloc_stmem(u_long size, void **phys_addr)
* for a new node in between.
*/
TAILQ_REMOVE(&free_list, mn, free_link);
TAILQ_NEXT(mn, free_link) = NULL;
mn->type = MNODE_USED;
size = mn->size; /* increase size. (or same) */
stmem_total -= mn->size;
splx(s);
@ -138,7 +138,7 @@ alloc_stmem(u_long size, void **phys_addr)
* and mark as not on free list
*/
TAILQ_INSERT_AFTER(&st_list, new, mn, link);
TAILQ_NEXT(mn, free_link) = NULL;
mn->type = MNODE_USED;
stmem_total -= size + sizeof(struct mem_node);
splx(s);
@ -150,7 +150,7 @@ void
free_stmem(void *mem)
{
struct mem_node *mn, *next, *prev;
int s;
int s;
if (mem == NULL)
return;
@ -163,48 +163,52 @@ free_stmem(void *mem)
/*
* check ahead of us.
*/
if (next != NULL && TAILQ_NEXT(next, free_link) != NULL) {
if (next->type == MNODE_FREE) {
/*
* if next is: a valid node and a free node. ==> merge
*/
TAILQ_INSERT_BEFORE(next, mn, free_link);
mn->type = MNODE_FREE;
TAILQ_REMOVE(&st_list, next, link);
TAILQ_REMOVE(&st_list, next, free_link);
TAILQ_REMOVE(&free_list, next, free_link);
stmem_total += mn->size + sizeof(struct mem_node);
mn->size += next->size + sizeof(struct mem_node);
}
if (prev != NULL && TAILQ_PREV(prev, freelist, free_link) != NULL) {
if (prev->type == MNODE_FREE) {
/*
* if prev is: a valid node and a free node. ==> merge
*/
if (TAILQ_NEXT(mn, free_link) == NULL)
if (mn->type != MNODE_FREE)
stmem_total += mn->size + sizeof(struct mem_node);
else {
/* already on free list */
TAILQ_REMOVE(&free_list, mn, free_link);
mn->type = MNODE_USED;
stmem_total += sizeof(struct mem_node);
}
TAILQ_REMOVE(&st_list, mn, link);
prev->size += mn->size + sizeof(struct mem_node);
} else if (TAILQ_NEXT(mn, free_link) == NULL) {
} else if (mn->type != MNODE_FREE) {
/*
* we still are not on free list and we need to be.
* <-- | -->
*/
while (next != NULL && prev != NULL) {
if (TAILQ_NEXT(next, free_link) != NULL) {
if (next->type == MNODE_FREE) {
TAILQ_INSERT_BEFORE(next, mn, free_link);
mn->type = MNODE_FREE;
break;
}
if (TAILQ_NEXT(prev, free_link) != NULL) {
if (prev->type == MNODE_FREE) {
TAILQ_INSERT_AFTER(&free_list, prev, mn,
free_link);
mn->type = MNODE_FREE;
break;
}
prev = TAILQ_PREV(prev, stlist, link);
next = TAILQ_NEXT(next, link);
}
if (TAILQ_NEXT(mn, free_link) == NULL) {
if (mn->type != MNODE_FREE) {
if (next == NULL) {
/*
* we are not on list so we can add
@ -214,6 +218,7 @@ free_stmem(void *mem)
} else {
TAILQ_INSERT_HEAD(&free_list,mn,free_link);
}
mn->type = MNODE_FREE;
}
stmem_total += mn->size;/* add our helpings to the pool. */
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: stalloc.h,v 1.5 2013/11/23 22:52:40 christos Exp $ */
/* $NetBSD: stalloc.h,v 1.6 2014/01/03 07:14:20 mlelstv Exp $ */
/*
* Copyright (c) 1994 Christian E. Hopps (allocator stuff)
@ -42,7 +42,10 @@ struct mem_node {
TAILQ_ENTRY(mem_node) link;
TAILQ_ENTRY(mem_node) free_link;
u_long size; /* size of memory following node. */
u_char type; /* free, used */
};
#define MNODE_FREE 0
#define MNODE_USED 1
#define ST_BLOCKSIZE (sizeof(long))
#define ST_BLOCKMASK (~(ST_BLOCKSIZE - 1))