[pypy-commit] stmgc bag: First tests pass
arigo
noreply at buildbot.pypy.org
Sat Jan 24 10:35:01 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: bag
Changeset: r1579:a46480cfd06d
Date: 2015-01-24 10:35 +0100
http://bitbucket.org/pypy/stmgc/changeset/a46480cfd06d/
Log: First tests pass
diff --git a/c7/stm/bag.c b/c7/stm/bag.c
--- a/c7/stm/bag.c
+++ b/c7/stm/bag.c
@@ -42,8 +42,7 @@
struct stm_bag_seg_s {
- struct deque_block_s *deque_left, *deque_middle, *deque_right;
- deque_idx_t deque_left_pos, deque_middle_pos, deque_right_pos;
+ uintptr_t *deque_left, *deque_middle, *deque_right;
struct list_s *abort_list;
};
@@ -59,12 +58,9 @@
for (i = 0; i < STM_NB_SEGMENTS; i++) {
struct stm_bag_seg_s *bs = &bag->by_segment[i];
struct deque_block_s *block = deque_new_block();
- bs->deque_left = block;
- bs->deque_middle = block;
- bs->deque_right = block;
- bs->deque_left_pos = 0;
- bs->deque_middle_pos = 0;
- bs->deque_right_pos = 0;
+ bs->deque_left = &block->items[0];
+ bs->deque_middle = &block->items[0];
+ bs->deque_right = &block->items[0];
LIST_CREATE(bs->abort_list);
}
return bag;
@@ -75,11 +71,49 @@
int i;
for (i = 0; i < STM_NB_SEGMENTS; i++) {
struct stm_bag_seg_s *bs = &bag->by_segment[i];
- while (bs->deque_left) {
- struct deque_block_s *block = bs->deque_left;
- bs->deque_left = block->next;
+ struct deque_block_s *block = deque_block(bs->deque_left);
+ while (block != NULL) {
+ struct deque_block_s *nextblock = block->next;
deque_free_block(block);
+ block = nextblock;
}
LIST_FREE(bs->abort_list);
}
}
+
+void stm_bag_add(stm_bag_t *bag, object_t *newobj)
+{
+ int i = STM_SEGMENT->segment_num - 1;
+ struct stm_bag_seg_s *bs = &bag->by_segment[i];
+ struct deque_block_s *block = deque_block(bs->deque_right);
+
+ *bs->deque_right++ = (uintptr_t)newobj;
+
+ if (bs->deque_right == &block->items[DEQUE_BLOCK_SIZE]) {
+ assert(block->next == NULL);
+ block->next = deque_new_block();
+ bs->deque_right = &block->next->items[0];
+ }
+}
+
+object_t *stm_bag_try_pop(stm_bag_t *bag)
+{
+ int i = STM_SEGMENT->segment_num - 1;
+ struct stm_bag_seg_s *bs = &bag->by_segment[i];
+ if (bs->deque_left == bs->deque_right) {
+ return NULL;
+ }
+ struct deque_block_s *block = deque_block(bs->deque_left);
+ uintptr_t result = *bs->deque_left++;
+
+ if (bs->deque_left == &block->items[DEQUE_BLOCK_SIZE]) {
+ bs->deque_left = &block->next->items[0];
+ deque_free_block(block);
+ }
+ return (object_t *)result;
+}
+
+void stm_bag_tracefn(stm_bag_t *bag, void visit(object_t **))
+{
+ abort();
+}
diff --git a/c7/stm/list.c b/c7/stm/list.c
--- a/c7/stm/list.c
+++ b/c7/stm/list.c
@@ -193,3 +193,22 @@
missing:
return false;
}
+
+
+/************************************************************/
+
+static struct deque_block_s *deque_new_block(void)
+{
+ void *mem;
+ struct deque_block_s *db;
+ size_t size = sizeof(struct deque_block_s);
+
+ assert((size & (size - 1)) == 0); /* a power of two */
+
+ if (posix_memalign(&mem, size, size) != 0)
+ stm_fatalerror("out of memory in deque_new_block"); /* XXX */
+
+ db = (struct deque_block_s *)mem;
+ db->next = NULL;
+ return db;
+}
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -222,23 +222,27 @@
/************************************************************/
#define DEQUE_BLOCK_SIZE 31
-typedef unsigned char deque_idx_t;
struct deque_block_s {
struct deque_block_s *next;
uintptr_t items[DEQUE_BLOCK_SIZE];
};
-static inline struct deque_block_s *deque_new_block(void)
-{
- struct deque_block_s *db = malloc(sizeof(struct deque_block_s));
- if (db == NULL)
- stm_fatalerror("out of memory in deque_new_block"); /* XXX */
- db->next = NULL;
- return db;
-}
+static struct deque_block_s *deque_new_block(void);
static inline void deque_free_block(struct deque_block_s *db)
{
free(db);
}
+
+static inline struct deque_block_s *deque_block(uintptr_t *inner_ptr)
+{
+ size_t size = sizeof(struct deque_block_s);
+ return (struct deque_block_s *)(((uintptr_t)inner_ptr) & ~(size - 1));
+}
+
+static inline bool deque_index_equal(uintptr_t *inner_ptr, uintptr_t index)
+{
+ struct deque_block_s *block = deque_block(inner_ptr);
+ return (inner_ptr == &block->items[index]);
+}
diff --git a/c7/stmgc.c b/c7/stmgc.c
--- a/c7/stmgc.c
+++ b/c7/stmgc.c
@@ -39,3 +39,4 @@
#include "stm/rewind_setjmp.c"
#include "stm/finalizer.c"
#include "stm/hashtable.c"
+#include "stm/bag.c"
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -559,6 +559,7 @@
void stm_bag_free(stm_bag_t *);
void stm_bag_add(stm_bag_t *, object_t *);
object_t *stm_bag_try_pop(stm_bag_t *);
+void stm_bag_tracefn(stm_bag_t *, void (object_t **));
/* ==================== END ==================== */
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -178,6 +178,16 @@
void _set_hashtable(object_t *obj, stm_hashtable_t *h);
stm_hashtable_t *_get_hashtable(object_t *obj);
+
+typedef struct stm_bag_s stm_bag_t;
+stm_bag_t *stm_bag_create(void);
+void stm_bag_free(stm_bag_t *);
+void stm_bag_add(stm_bag_t *, object_t *);
+object_t *stm_bag_try_pop(stm_bag_t *);
+void stm_bag_tracefn(stm_bag_t *, void (object_t **));
+
+void _set_bag(object_t *obj, stm_bag_t *h);
+stm_bag_t *_get_bag(object_t *obj);
""")
@@ -308,6 +318,20 @@
return *(stm_hashtable_t *TLPREFIX *)field_addr;
}
+void _set_bag(object_t *obj, stm_bag_t *bag)
+{
+ stm_char *field_addr = ((stm_char*)obj);
+ field_addr += SIZEOF_MYOBJ; /* header */
+ *(stm_bag_t *TLPREFIX *)field_addr = bag;
+}
+
+stm_bag_t *_get_bag(object_t *obj)
+{
+ stm_char *field_addr = ((stm_char*)obj);
+ field_addr += SIZEOF_MYOBJ; /* header */
+ return *(stm_bag_t *TLPREFIX *)field_addr;
+}
+
void _set_ptr(object_t *obj, int n, object_t *v)
{
long nrefs = (long)((myobj_t*)obj)->type_id - 421420;
@@ -344,6 +368,9 @@
if (myobj->type_id == 421418) { /* hashtable entry */
return sizeof(struct stm_hashtable_entry_s);
}
+ if (myobj->type_id == 421417) { /* bag */
+ return sizeof(struct myobj_s) + 1 * sizeof(void*);
+ }
/* basic case: tid equals 42 plus the size of the object */
assert(myobj->type_id >= 42 + sizeof(struct myobj_s));
assert((myobj->type_id - 42) >= 16);
@@ -374,6 +401,12 @@
object_t **ref = &((struct stm_hashtable_entry_s *)myobj)->object;
visit(ref);
}
+ if (myobj->type_id == 421417) {
+ /* bag */
+ stm_bag_t *b = *((stm_bag_t **)(myobj + 1));
+ stm_bag_tracefn(b, visit);
+ return;
+ }
if (myobj->type_id < 421420) {
/* basic case: no references */
return;
@@ -394,6 +427,7 @@
struct myobj_s *myobj = (struct myobj_s*)obj;
assert(myobj->type_id != 421419);
assert(myobj->type_id != 421418);
+ assert(myobj->type_id != 421417);
if (myobj->type_id < 421420) {
/* basic case: no references */
return;
@@ -514,6 +548,18 @@
assert lib._get_type_id(o) == 421419
return lib._get_hashtable(o)
+def stm_allocate_bag():
+ o = lib.stm_allocate(16)
+ tid = 421417
+ lib._set_type_id(o, tid)
+ h = lib.stm_bag_create()
+ lib._set_bag(o, h)
+ return o
+
+def get_bag(o):
+ assert lib._get_type_id(o) == 421417
+ return lib._get_bag(o)
+
def stm_get_weakref(o):
return lib._get_weakref(o)
diff --git a/c7/test/test_bag.py b/c7/test/test_bag.py
new file mode 100644
--- /dev/null
+++ b/c7/test/test_bag.py
@@ -0,0 +1,69 @@
+from support import *
+import py
+
+
+class BagLooksEmpty(Exception):
+ pass
+
+def b_add(o, nvalue):
+ b = get_bag(o)
+ lib.stm_bag_add(b, nvalue)
+
+def b_pop(o):
+ b = get_bag(o)
+ r = lib.stm_bag_try_pop(b)
+ if not r:
+ raise BagLooksEmpty
+ return r
+
+
+class BaseTestBag(BaseTest):
+
+ def setup_method(self, meth):
+ BaseTest.setup_method(self, meth)
+ #
+ @ffi.callback("void(object_t *)")
+ def light_finalizer(obj):
+ print 'light_finalizer:', obj
+ try:
+ assert lib._get_type_id(obj) == 421417
+ self.seen_bags -= 1
+ except:
+ self.errors.append(sys.exc_info()[2])
+ raise
+
+ lib.stmcb_light_finalizer = light_finalizer
+ self._light_finalizer_keepalive = light_finalizer
+ self.seen_bags = 0
+ self.errors = []
+
+ def teardown_method(self, meth):
+ BaseTest.teardown_method(self, meth)
+ lib.stmcb_light_finalizer = ffi.NULL
+ assert self.errors == []
+ assert self.seen_bags == 0
+
+ def allocate_bag(self):
+ q = stm_allocate_bag()
+ lib.stm_enable_light_finalizer(q)
+ self.seen_bags += 1
+ return q
+
+
+class TestBag(BaseTestBag):
+
+ def test_small_push_pop(self):
+ self.start_transaction()
+ q = self.allocate_bag()
+ lp1 = stm_allocate(16)
+ lp2 = stm_allocate(16)
+ for i in range(4):
+ b_add(q, lp1)
+ b_add(q, lp2)
+ for j in range(4):
+ got = b_pop(q)
+ assert got == lp1
+ got = b_pop(q)
+ assert got == lp2
+ py.test.raises(BagLooksEmpty, b_pop, q)
+ py.test.raises(BagLooksEmpty, b_pop, q)
More information about the pypy-commit
mailing list