scripts

misc scripts and tools
git clone git://git.2f30.org/scripts
Log | Files | Refs

commit 2523880dc2e339eef0e00e76848721f4b2d27812
parent 859527cd00e6cb2e44b434b8c8db0a64f2ba8b4f
Author: sin <sin@2f30.org>
Date:   Fri,  2 Aug 2013 10:20:09 +0100

Make rballoc thread-safe

Diffstat:
Mrandom/rballoc.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 64 insertions(+), 12 deletions(-)

diff --git a/random/rballoc.c b/random/rballoc.c @@ -6,6 +6,7 @@ #include <string.h> #include <errno.h> #include "tree.h" +#include "spinlock.h" enum { PAGESIZE = 4096 }; @@ -17,6 +18,7 @@ struct node { RB_HEAD(free_tree, node) ft = RB_INITIALIZER(&ft); RB_HEAD(alloc_tree, node) at = RB_INITIALIZER(&at); +static spinlock_t rblock; static int ft_cmp(struct node *a, struct node *b); RB_PROTOTYPE(free_tree, node, entry, ft_cmp) @@ -109,6 +111,7 @@ malloc(size_t siz) if (!siz) return NULL; + lock(&rblock); /* Lookup in the free tree for a block greater * than or equal to `siz' bytes */ n.siz = siz; @@ -117,20 +120,25 @@ malloc(size_t siz) /* No available free block, create a new block * and add it to the alloc tree */ an = alloc_object(sizeof(*an)); - if (!an) + if (!an) { + unlock(&rblock); return NULL; + } p = alloc_block(siz); if (!p) { free_object(an, sizeof(*an)); + unlock(&rblock); return NULL; } an->buf = p; an->siz = siz; RB_INSERT(alloc_tree, &at, an); + unlock(&rblock); return an->buf; } an = RB_REMOVE(free_tree, &ft, res); RB_INSERT(alloc_tree, &at, an); + unlock(&rblock); return an->buf; } @@ -138,28 +146,66 @@ void * realloc(void *oldp, size_t siz) { struct node n, *res; - void *p; + struct node *oldan, *newan; + struct node *fn; if (!oldp) return malloc(siz); - if (!siz && oldp) { - free(oldp); + if (!siz) { + if (oldp) + free(oldp); return NULL; } + lock(&rblock); n.buf = oldp; res = RB_FIND(alloc_tree, &at, &n); if (res) { /* If we were asked to shrink the allocated space * just re-use it */ - if (res->siz >= siz) + if (res->siz >= siz) { + unlock(&rblock); return res->buf; - p = malloc(siz); - if (!p) - return NULL; - memcpy(p, res->buf, siz < res->siz ? siz : res->siz); - free(res->buf); - return p; + } + oldan = res; + /* Lookup in the free tree for a block greater + * than or equal to `siz' bytes */ + n.siz = siz; + res = RB_NFIND(free_tree, &ft, &n); + if (!res) { + /* No available free block, create a new block + * and add it to the alloc tree */ + newan = alloc_object(sizeof(*newan)); + if (!newan) { + unlock(&rblock); + return NULL; + } + newan->buf = alloc_block(siz); + if (!newan->buf) { + free_object(newan, sizeof(*newan)); + unlock(&rblock); + return NULL; + } + newan->siz = siz; + RB_INSERT(alloc_tree, &at, newan); + } else { + /* Grab the block from the free tree instead */ + newan = RB_REMOVE(free_tree, &ft, res); + RB_INSERT(alloc_tree, &at, newan); + } + /* Copy over the contents at `oldp' */ + memcpy(newan->buf, oldan->buf, + siz < oldan->siz ? siz : oldan->siz); + /* Free `oldp' */ + n.buf = oldan; + res = RB_FIND(alloc_tree, &at, &n); + if (res) { + fn = RB_REMOVE(alloc_tree, &at, res); + RB_INSERT(free_tree, &ft, fn); + } + unlock(&rblock); + return newan->buf; } + unlock(&rblock); return NULL; } @@ -182,12 +228,14 @@ free(void *p) if (!p) return; + lock(&rblock); n.buf = p; res = RB_FIND(alloc_tree, &at, &n); if (res) { fn = RB_REMOVE(alloc_tree, &at, res); RB_INSERT(free_tree, &ft, fn); } + unlock(&rblock); } int @@ -218,10 +266,14 @@ malloc_usable_size(void *p) if (!p) return 0; + lock(&rblock); n.buf = p; res = RB_FIND(alloc_tree, &at, &n); - if (res) + if (res) { + unlock(&rblock); return res->siz; + } + unlock(&rblock); return 0; }