klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 293848a0bcbf6fa75334a0a64d4d5251c325f8bc
parent a1f42c7a067ce33801360f7766e002929a120f51
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Fri, 24 Aug 2012 02:31:07 -0300

Added locking to kbytevector functions.

Diffstat:
Msrc/kbytevector.c | 57+++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/kbytevector.h | 2+-
Msrc/kghelpers.c | 2+-
3 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/src/kbytevector.c b/src/kbytevector.c @@ -24,15 +24,12 @@ TValue kbytevector_new_bs_g(klisp_State *K, bool m, const uint8_t *buf, kbytevector_new_bs_imm(K, buf, size); } -/* -** Constructors for immutable bytevectors -*/ +/* Looks for a bytevector in the stringtable and returns a pointer + to it if found or NULL otherwise. */ -/* XXX lock? */ -/* main constructor for immutable bytevectors */ -TValue kbytevector_new_bs_imm(klisp_State *K, const uint8_t *buf, uint32_t size) +/* LOCK: GIL should be acquired */ +static uint32_t get_bytevector_hash(const uint8_t *buf, uint32_t size) { - /* first check to see if it's in the stringtable */ uint32_t h = size; /* seed */ size_t step = (size>>5)+1; /* if bytevector is too long, don't hash all its bytes */ @@ -40,6 +37,13 @@ TValue kbytevector_new_bs_imm(klisp_State *K, const uint8_t *buf, uint32_t size) for (size1 = size; size1 >= step; size1 -= step) /* compute hash */ h = h ^ ((h<<5)+(h>>2)+ buf[size1-1]); + return h; +} + +static Bytevector *search_in_bb_table(klisp_State *K, const uint8_t *buf, + uint32_t size, uint32_t h) +{ + for (GCObject *o = G(K)->strt.hash[lmod(h, G(K)->strt.size)]; o != NULL; o = o->gch.next) { klisp_assert(o->gch.tt == K_TKEYWORD || o->gch.tt == K_TSYMBOL || @@ -51,13 +55,32 @@ TValue kbytevector_new_bs_imm(klisp_State *K, const uint8_t *buf, uint32_t size) if (tb->size == size && (memcmp(buf, tb->b, size) == 0)) { /* bytevector may be dead */ if (isdead(G(K), o)) changewhite(o); - return gc2bytevector(o); + return tb; } - } + } + return NULL; +} + + +/* +** Constructors for immutable bytevectors +*/ + +/* main constructor for immutable bytevectors */ +TValue kbytevector_new_bs_imm(klisp_State *K, const uint8_t *buf, uint32_t size) +{ + uint32_t h = get_bytevector_hash(buf, size); + klisp_lock(K); + /* first check to see if it's in the stringtable */ + Bytevector *new_bb = search_in_bb_table(K, buf, size, h); + + if (new_bb != NULL) { /* found */ + klisp_unlock(K); + return gc2bytevector(new_bb); + } /* If it exits the loop, it means it wasn't found, hash is still in h */ /* REFACTOR: move all of these to a new function */ - Bytevector *new_bb; if (size > (SIZE_MAX - sizeof(Bytevector))) klispM_toobig(K); @@ -94,7 +117,8 @@ TValue kbytevector_new_bs_imm(klisp_State *K, const uint8_t *buf, uint32_t size) klispS_resize(K, tb->size*2); /* too crowded */ krooted_tvs_pop(K); } - + + klisp_unlock(K); return ret_tv; } @@ -113,6 +137,7 @@ TValue kbytevector_new_s(klisp_State *K, uint32_t size) return G(K)->empty_bytevector; } + klisp_lock(K); new_bb = klispM_malloc(K, sizeof(Bytevector) + size); /* header + gc_fields */ @@ -123,7 +148,7 @@ TValue kbytevector_new_s(klisp_State *K, uint32_t size) new_bb->size = size; /* the buffer is initialized elsewhere */ - + klisp_unlock(K); return gc2bytevector(new_bb); } @@ -154,7 +179,7 @@ TValue kbytevector_new_sf(klisp_State *K, uint32_t size, uint8_t fill) } /* both obj1 and obj2 should be bytevectors */ -bool kbytevector_equalp(TValue obj1, TValue obj2) +bool kbytevector_equalp(klisp_State *K, TValue obj1, TValue obj2) { klisp_assert(ttisbytevector(obj1) && ttisbytevector(obj2)); @@ -162,8 +187,12 @@ bool kbytevector_equalp(TValue obj1, TValue obj2) Bytevector *bytevector2 = tv2bytevector(obj2); if (bytevector1->size == bytevector2->size) { - return (bytevector1->size == 0) || + bool res; + klisp_lock(K); + res = (bytevector1->size == 0) || (memcmp(bytevector1->b, bytevector2->b, bytevector1->size) == 0); + klisp_unlock(K); + return res; } else { return false; } diff --git a/src/kbytevector.h b/src/kbytevector.h @@ -38,7 +38,7 @@ TValue kbytevector_new_sf(klisp_State *K, uint32_t size, uint8_t fill); /* both obj1 and obj2 should be bytevectors, this compares byte by byte and doesn't differentiate immutable from mutable bytevectors */ -bool kbytevector_equalp(TValue obj1, TValue obj2); +bool kbytevector_equalp(klisp_State *K, TValue obj1, TValue obj2); bool kbytevectorp(TValue obj); bool kimmutable_bytevectorp(TValue obj); bool kmutable_bytevectorp(TValue obj); diff --git a/src/kghelpers.c b/src/kghelpers.c @@ -1066,7 +1066,7 @@ bool equal2p(klisp_State *K, TValue obj1, TValue obj2) } break; case K_TBYTEVECTOR: - if (!kbytevector_equalp(obj1, obj2)) { + if (!kbytevector_equalp(K, obj1, obj2)) { result = false; goto end; }