summaryrefslogtreecommitdiff
path: root/lib/resource.c
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2023-04-24 10:39:13 +0200
committerMaria Matejka <mq@ucw.cz>2023-04-24 10:39:13 +0200
commitfa8848aca3f0473412f3ae6288d71dee8458bcfa (patch)
tree20aa1c64f866079684f4923f857021baff4d2b53 /lib/resource.c
parent942d3cbcdd548a73ecc1915a97e297e9bf0bb5e6 (diff)
parent22f54eaee6c6dbe12ad7bb0ee1da09e3e026b970 (diff)
Merge branch 'mq-resource-locking' into thread-next
Diffstat (limited to 'lib/resource.c')
-rw-r--r--lib/resource.c147
1 files changed, 107 insertions, 40 deletions
diff --git a/lib/resource.c b/lib/resource.c
index 94b8d019..2071a411 100644
--- a/lib/resource.c
+++ b/lib/resource.c
@@ -46,6 +46,16 @@ static struct resclass pool_class = {
pool root_pool;
+static void
+rp_init(pool *z, struct domain_generic *dom, const char *name)
+{
+ ASSERT_DIE(DG_IS_LOCKED(dom));
+
+ z->name = name;
+ z->domain = dom;
+ z->inside = (TLIST_LIST(resource)) {};
+}
+
/**
* rp_new - create a resource pool
* @p: parent pool
@@ -55,71 +65,106 @@ pool root_pool;
* parent pool.
*/
pool *
-rp_new(pool *p, const char *name)
+rp_new(pool *p, struct domain_generic *dom, const char *name)
{
pool *z = ralloc(p, &pool_class);
- z->name = name;
- init_list(&z->inside);
+
+ if (dg_order(p->domain) > dg_order(dom))
+ bug("Requested reverse order pool creation: %s (%d) can't be a parent of %s (%d)",
+ domain_name(p->domain), dg_order(p->domain),
+ domain_name(dom), dg_order(dom));
+
+ if ((dg_order(p->domain) == dg_order(dom)) && (p->domain != dom))
+ bug("Requested incomparable order pool creation: %s (%d) can't be a parent of %s (%d)",
+ domain_name(p->domain), dg_order(p->domain),
+ domain_name(dom), dg_order(dom));
+
+ rp_init(z, dom, name);
return z;
}
pool *
-rp_newf(pool *p, const char *fmt, ...)
+rp_vnewf(pool *p, struct domain_generic *dom, const char *fmt, va_list args)
{
- pool *z = rp_new(p, NULL);
+ pool *z = rp_new(p, dom, NULL);
+ z->name = mb_vsprintf(p, fmt, args);
+ return z;
+}
+pool *
+rp_newf(pool *p, struct domain_generic *dom, const char *fmt, ...)
+{
va_list args;
va_start(args, fmt);
- z->name = mb_vsprintf(p, fmt, args);
+ pool *z = rp_vnewf(p, dom, fmt, args);
va_end(args);
return z;
}
+#define POOL_LOCK \
+ struct domain_generic *dom = p->domain; \
+ int locking = !DG_IS_LOCKED(dom); \
+ if (locking) \
+ DG_LOCK(dom); \
+
+#define POOL_UNLOCK if (locking) DG_UNLOCK(dom);\
+
+void rp_free(pool *p)
+{
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+ rfree(p);
+}
static void
pool_free(resource *P)
{
pool *p = (pool *) P;
- resource *r, *rr;
- r = HEAD(p->inside);
- while (rr = (resource *) r->n.next)
+ POOL_LOCK;
+ WALK_TLIST_DELSAFE(resource, r, &p->inside)
{
r->class->free(r);
xfree(r);
- r = rr;
}
+ POOL_UNLOCK;
}
+
static void
pool_dump(resource *P, unsigned indent)
{
pool *p = (pool *) P;
- resource *r;
+
+ POOL_LOCK;
debug("%s\n", p->name);
- WALK_LIST(r, p->inside)
+ WALK_TLIST_DELSAFE(resource, r, &p->inside)
rdump(r, indent + 3);
+
+ POOL_UNLOCK;
}
static struct resmem
pool_memsize(resource *P)
{
pool *p = (pool *) P;
- resource *r;
struct resmem sum = {
.effective = 0,
.overhead = sizeof(pool) + ALLOC_OVERHEAD,
};
- WALK_LIST(r, p->inside)
+ POOL_LOCK;
+
+ WALK_TLIST(resource, r, &p->inside)
{
struct resmem add = rmemsize(r);
sum.effective += add.effective;
sum.overhead += add.overhead;
}
+ POOL_UNLOCK;
+
return sum;
}
@@ -127,14 +172,25 @@ static resource *
pool_lookup(resource *P, unsigned long a)
{
pool *p = (pool *) P;
- resource *r, *q;
+ resource *q = NULL;
+
+ POOL_LOCK;
- WALK_LIST(r, p->inside)
+ WALK_TLIST(resource, r, &p->inside)
if (r->class->lookup && (q = r->class->lookup(r, a)))
- return q;
- return NULL;
+ break;
+
+ POOL_UNLOCK;
+ return q;
}
+static pool *
+resource_parent(resource *r)
+{
+ return SKIP_BACK(pool, inside, resource_enlisted(r));
+}
+
+
/**
* rmove - move a resource
* @res: resource
@@ -146,13 +202,13 @@ pool_lookup(resource *P, unsigned long a)
void rmove(void *res, pool *p)
{
resource *r = res;
+ pool *orig = resource_parent(r);
- if (r)
- {
- if (r->n.next)
- rem_node(&r->n);
- add_tail(&p->inside, &r->n);
- }
+ ASSERT_DIE(DG_IS_LOCKED(orig->domain));
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+
+ resource_rem_node(&orig->inside, r);
+ resource_add_tail(&p->inside, r);
}
/**
@@ -173,8 +229,10 @@ rfree(void *res)
if (!r)
return;
- if (r->n.next)
- rem_node(&r->n);
+ pool *orig = resource_parent(r);
+ ASSERT_DIE(DG_IS_LOCKED(orig->domain));
+ resource_rem_node(&orig->inside, r);
+
r->class->free(r);
r->class = NULL;
xfree(r);
@@ -233,12 +291,14 @@ rmemsize(void *res)
void *
ralloc(pool *p, struct resclass *c)
{
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+
resource *r = xmalloc(c->size);
bzero(r, c->size);
r->class = c;
- if (p)
- add_tail(&p->inside, &r->n);
+ resource_add_tail(&p->inside, r);
+
return r;
}
@@ -278,28 +338,29 @@ resource_init(void)
rcu_init();
resource_sys_init();
- root_pool.r.class = &pool_class;
- root_pool.name = "Root";
- init_list(&root_pool.inside);
- tmp_init(&root_pool);
+ rp_init(&root_pool, the_bird_domain.the_bird, "Root");
+ tmp_init(&root_pool, the_bird_domain.the_bird);
}
_Thread_local struct tmp_resources tmp_res;
void
-tmp_init(pool *p)
+tmp_init(pool *p, struct domain_generic *dom)
{
tmp_res.lp = lp_new_default(p);
tmp_res.parent = p;
- tmp_res.pool = rp_new(p, "TMP");
+ tmp_res.pool = rp_new(p, dom, "TMP");
+ tmp_res.domain = dom;
}
void
tmp_flush(void)
{
+ ASSERT_DIE(DG_IS_LOCKED(tmp_res.domain));
+
lp_flush(tmp_linpool);
- rfree(tmp_res.pool);
- tmp_res.pool = rp_new(tmp_res.parent, "TMP");
+ rp_free(tmp_res.pool);
+ tmp_res.pool = rp_new(tmp_res.parent, tmp_res.domain, "TMP");
}
@@ -379,11 +440,13 @@ static struct resclass mb_class = {
void *
mb_alloc(pool *p, unsigned size)
{
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+
struct mblock *b = xmalloc(sizeof(struct mblock) + size);
b->r.class = &mb_class;
- b->r.n = (node) {};
- add_tail(&p->inside, &b->r.n);
+ b->r.n = (struct resource_node) {};
+ resource_add_tail(&p->inside, &b->r);
b->size = size;
return b->data;
}
@@ -428,10 +491,14 @@ void *
mb_realloc(void *m, unsigned size)
{
struct mblock *b = SKIP_BACK(struct mblock, data, m);
+ struct pool *p = resource_parent(&b->r);
+
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
b = xrealloc(b, sizeof(struct mblock) + size);
- update_node(&b->r.n);
b->size = size;
+
+ resource_update_node(&p->inside, &b->r);
return b->data;
}
@@ -449,7 +516,7 @@ mb_free(void *m)
return;
struct mblock *b = SKIP_BACK(struct mblock, data, m);
- rfree(b);
+ rfree(&b->r);
}