ref: 6cea0ac16962d9de3004a751302dc743c321fa95
parent: af76a32eea6c19a5f608680f37bfc5e370a2ab36
author: qwx <qwx@sciops.net>
date: Sat Jun 4 08:20:20 EDT 2022
zalloc: hide implementation and add checks really complicated now
--- a/asif.h
+++ b/asif.h
@@ -106,19 +106,13 @@
void* emalloc(ulong);
typedef struct Zpool Zpool;
-typedef struct Znode Znode;
-struct Znode{
- Znode *next;
- Znode *prev;
+struct Zpool{
+ usize elsize;
void data[];
};
-struct Zpool{
- int elsize;
- Znode;
-};
-void zfree(Znode*, Zpool*);
+void zfree(void*);
void* zalloc(Zpool*);
-Zpool* znew(int);
+Zpool* znew(usize);
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
--- a/zalloc.c
+++ b/zalloc.c
@@ -2,15 +2,65 @@
#include <libc.h>
#include "asif.h"
-/* no nodes are ever freed, left to be reclaimed by the kernel on exit */
+/* no nodes are ever freed, left to be reclaimed by the kernel on exit
+ * got more complicated, but should be able to detect some bugs...
+ * unsuitable for very large collections probably */
+
+typedef struct Zhouse Zhouse;
+typedef struct Znode Znode;
+typedef struct Zhdr Zhdr;
+typedef struct Ztail Ztail;
+struct Zhdr{
+ Zhouse *z;
+ Znode *next;
+ Znode *prev;
+};
+struct Znode{
+ Zhdr;
+ void data[];
+};
+struct Ztail{
+ Zpool *z;
+};
+struct Zhouse{
+ Zpool;
+ Znode;
+};
+
enum{
Ninc = 128,
};
+static Ztail *
+n2t(Znode *p)
+{
+ return (Ztail *)((uchar *)p + sizeof(Zhdr) + p->z->elsize);
+}
+
+static Znode *
+v2n(uchar *data)
+{
+ return (Znode *)(data - sizeof(Zhdr));
+}
+
static void
-zlink(Znode *p, Zpool *z)
+zcheckpool(Znode *p, Zhouse *z)
{
- assert(p != nil && z != nil);
+ Ztail *t;
+
+ assert(p == nil || p != z);
+ assert(z != nil && z->elsize > 0);
+ if(p != nil){
+ assert(p->z == z);
+ t = n2t(p);
+ assert(t->z == z);
+ }
+}
+
+static void
+zlink(Znode *p, Zhouse *z)
+{
+ zcheckpool(p, z);
p->prev = z->prev;
p->next = &z->Znode;
z->prev->next = p;
@@ -18,57 +68,78 @@
}
static Znode *
-zunlink(Zpool *z)
+zpop(Zhouse *z)
{
- Znode *q;
+ Znode *p;
- 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;
+ p = z->next;
+ assert(p != z);
+ zcheckpool(p, z);
+ p->next->prev = &z->Znode;
+ z->next = p->next;
+ p->prev = p->next = nil;
+ return p;
}
static void
-zfeed(Zpool *z)
+_zfree(Znode *p)
{
- int n;
- uchar *p, *q;
+ Zhouse *z;
- assert(z != nil && z->elsize > 0);
- if(z->next != z)
+ if(p == nil)
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);
+ z = p->z;
+ zcheckpool(p, z);
+ memset(p->data, 0, z->elsize);
+ zlink(p, z);
}
void
-zfree(Znode *p, Zpool *z)
+zfree(void *data)
{
- if(p == nil)
+ if(data == nil)
return;
- assert(z != nil);
- memset(p->data, 0, z->elsize);
- zlink(p, z);
+ _zfree(v2n(data));
}
+static void
+zfeed(Zhouse *z)
+{
+ ulong n;
+ uchar *u, *v;
+ Znode *p;
+ Ztail *t;
+
+ if(z->next != z)
+ return;
+ zcheckpool(nil, z);
+ n = sizeof(Zhdr) + z->elsize + sizeof *t;
+ u = emalloc(Ninc * n);
+ for(v=u; v<u+Ninc*n; v+=n){
+ p = (Znode *)v;
+ t = n2t(p);
+ p->z = z->z;
+ t->z = z->z;
+ zlink(p, z);
+ }
+}
+
void *
-zalloc(Zpool *z)
+zalloc(Zpool *zp)
{
Znode *p;
+ Zhouse *z;
+ z = (Zhouse *)zp;
zfeed(z);
- p = zunlink(z);
+ p = zpop(z);
return p->data;
}
Zpool *
-znew(int elsize)
+znew(usize elsize)
{
- Zpool *z;
+ Zhouse *z;
assert(elsize > 0);
z = emalloc(sizeof *z);