shithub: asif

Download patch

ref: af76a32eea6c19a5f608680f37bfc5e370a2ab36
parent: 99e8d835b687b9e946293b817d2e2b81ce76907e
author: qwx <qwx@sciops.net>
date: Fri Jun 3 22:34:40 EDT 2022

add zalloc: general free lists; field tests pending

--- a/asif.h
+++ b/asif.h
@@ -49,12 +49,10 @@
 	QNode *up;
 	QNode *down;
 	void *aux;
-
-	QNode *prev;
-	QNode *next;
 };
 QNode*	qtmerge(QNode*);
 QNode*	qtsplit(QNode*);
+QNode*	qtnew(void);
 
 u32int	next32pow2(u32int);
 int	lsb64(uvlong);
@@ -106,6 +104,21 @@
 char*	estrdup(char*);
 void*	erealloc(void*, ulong, ulong);
 void*	emalloc(ulong);
+
+typedef struct Zpool Zpool;
+typedef struct Znode Znode;
+struct Znode{
+	Znode *next;
+	Znode *prev;
+	void data[];
+};
+struct Zpool{
+	int elsize;
+	Znode;
+};
+void	zfree(Znode*, Zpool*);
+void*	zalloc(Zpool*);
+Zpool*	znew(int);
 
 #define MIN(a,b)	((a) <= (b) ? (a) : (b))
 #define MAX(a,b)	((a) >= (b) ? (a) : (b))
--- a/qtree.c
+++ b/qtree.c
@@ -2,50 +2,8 @@
 #include <libc.h>
 #include "asif.h"
 
-enum{
-	Ninc = 128,
-};
+static Zpool *zpool;
 
-/* no nodes are ever freed */
-static QNode freeq = { .next = &freeq, .prev = &freeq };
-
-static void
-qtlink(QNode *q)
-{
-	assert(q != nil);
-	q->prev = freeq.prev;
-	q->next = &freeq;
-	freeq.prev->next = q;
-	freeq.prev = q;
-}
-
-static void
-qtfree(QNode *q)
-{
-	if(q == nil)
-		return;
-	free(q->aux);
-	memset(q, 0, sizeof *q);
-	qtlink(q);
-}
-
-static QNode *
-qtalloc(void)
-{
-	QNode *q, *fq;
-
-	if(freeq.next == &freeq){
-		q = emalloc(Ninc * sizeof *q);
-		for(fq=q; fq<q+Ninc; fq++)
-			qtlink(fq);
-	}
-	q = freeq.next;
-	q->next->prev = &freeq;
-	freeq.next = q->next;
-	q->prev = q->next = nil;
-	return q;
-}
-
 QNode *
 qtmerge(QNode *q)
 {
@@ -55,10 +13,10 @@
 	qtmerge(q->right);
 	qtmerge(q->up);
 	qtmerge(q->down);
-	qtfree(q->left);
-	qtfree(q->right);
-	qtfree(q->up);
-	qtfree(q->down);
+	zfree(q->left, zpool);
+	zfree(q->right, zpool);
+	zfree(q->up, zpool);
+	zfree(q->down, zpool);
 	q->left = q->right = q->up = q->down = nil;
 	return q;
 }
@@ -66,10 +24,23 @@
 QNode *
 qtsplit(QNode *q)
 {
+	if(q == nil)
+		return nil;
 	assert(q->left == nil && q->right == nil && q->up == nil && q->down == nil);
-	q->left = qtalloc();
-	q->right = qtalloc();
-	q->up = qtalloc();
-	q->down = qtalloc();
+	q->left = zalloc(zpool);
+	q->right = zalloc(zpool);
+	q->up = zalloc(zpool);
+	q->down = zalloc(zpool);
+	return q;
+}
+
+QNode *
+qtnew(void)
+{
+	QNode *q;
+
+	q = emalloc(sizeof *q);
+	if(zpool == nil)
+		zpool = znew(sizeof *q);
 	return q;
 }
--- /dev/null
+++ b/zalloc.c
@@ -1,0 +1,79 @@
+#include <u.h>
+#include <libc.h>
+#include "asif.h"
+
+/* no nodes are ever freed, left to be reclaimed by the kernel on exit */
+enum{
+	Ninc = 128,
+};
+
+static void
+zlink(Znode *p, Zpool *z)
+{
+	assert(p != nil && z != nil);
+	p->prev = z->prev;
+	p->next = &z->Znode;
+	z->prev->next = p;
+	z->prev = p;
+}
+
+static Znode *
+zunlink(Zpool *z)
+{
+	Znode *q;
+
+	assert(z != nil && z->next != nil);
+	q = z->next;
+	q->next->prev = &z->Znode;
+	z->next = q->next;
+	q->prev = q->next = nil;
+	return q;
+}
+
+static void
+zfeed(Zpool *z)
+{
+	int n;
+	uchar *p, *q;
+
+	assert(z != nil && z->elsize > 0);
+	if(z->next != z)
+		return;
+	n = z->elsize + sizeof *z;
+	p = emalloc(Ninc * n);		// see comment
+	for(q=p; q<p+Ninc*n; q+=n)
+		zlink((Znode*)q, z);
+}
+
+void
+zfree(Znode *p, Zpool *z)
+{
+	if(p == nil)
+		return;
+	assert(z != nil);
+	memset(p->data, 0, z->elsize);
+	zlink(p, z);
+}
+
+void *
+zalloc(Zpool *z)
+{
+	Znode *p;
+
+	zfeed(z);
+	p = zunlink(z);
+	return p->data;
+}
+
+Zpool *
+znew(int elsize)
+{
+	Zpool *z;
+
+	assert(elsize > 0);
+	z = emalloc(sizeof *z);
+	z->elsize = elsize;
+	z->next = z->prev = z;
+	zfeed(z);
+	return z;
+}