Author: Armin Rigo <[email protected]>
Branch: c7-refactor
Changeset: r853:9fb1364ed14f
Date: 2014-02-25 09:38 +0100
http://bitbucket.org/pypy/stmgc/changeset/9fb1364ed14f/
Log: Use the trees to implement young_outside_nursery, step 1.
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -179,6 +179,7 @@
}
assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
+ assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery));
assert(STM_PSEGMENT->objects_pointing_to_nursery == NULL);
assert(STM_PSEGMENT->large_overflow_objects == NULL);
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -81,6 +81,11 @@
current transaction spanned a minor collection. */
struct list_s *large_overflow_objects;
+ /* List of all young objects outside the nursery ("young" in the
+ sense that they should be in the nursery, but were too big for
+ that). */
+ struct tree_s *young_outside_nursery;
+
/* Start time: to know approximately for how long a transaction has
been running, in contention management */
uint64_t start_time;
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -105,8 +105,8 @@
static void tree_clear(struct tree_s *tree);
//static inline void tree_delete_not_used_any_more(struct tree_s *tree)...
-static inline bool tree_any_entry(struct tree_s *tree) {
- return tree->raw_current != tree->raw_start;
+static inline bool tree_is_cleared(struct tree_s *tree) {
+ return tree->raw_current == tree->raw_start;
}
#define _TREE_LOOP(tree, item, INITIAL, _PLUS_) \
@@ -177,7 +177,8 @@
static wlog_t *_tree_find(char *entry, uintptr_t addr);
static void _tree_compress(struct tree_s *tree) __attribute__((unused));
static void tree_insert(struct tree_s *tree, uintptr_t addr, uintptr_t val);
-static bool tree_delete_item(struct tree_s *tree, uintptr_t addr);
+static bool tree_delete_item(struct tree_s *tree, uintptr_t addr)
+ __attribute__((unused));
static inline bool tree_contains(struct tree_s *tree, uintptr_t addr)
{
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -182,6 +182,19 @@
memset(realnursery, 0, size);
STM_SEGMENT->nursery_current = (stm_char *)_stm_nursery_start;
+
+ /* free any object left from 'young_outside_nursery' */
+ if (!tree_is_cleared(STM_PSEGMENT->young_outside_nursery)) {
+ mutex_pages_lock();
+
+ wlog_t *item;
+ TREE_LOOP_FORWARD(*STM_PSEGMENT->young_outside_nursery, item) {
+ _stm_large_free(stm_object_pages + item->addr);
+ } TREE_LOOP_END;
+
+ tree_clear(STM_PSEGMENT->young_outside_nursery);
+ mutex_pages_unlock();
+ }
}
static void minor_collection(bool commit)
@@ -268,7 +281,14 @@
object_t *_stm_allocate_external(ssize_t size_rounded_up)
{
- abort();//...
+ /* XXX force a minor/major collection if needed */
+
+ char *result = allocate_outside_nursery_large(size_rounded_up);
+ memset(result, 0, size_rounded_up);
+
+ object_t *o = (object_t *)(result - stm_object_pages);
+ tree_insert(STM_PSEGMENT->young_outside_nursery, (intptr_t)o, 0);
+ return o;
}
#ifdef STM_TESTS
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -56,6 +56,7 @@
pr->objects_pointing_to_nursery = NULL;
pr->large_overflow_objects = NULL;
pr->modified_old_objects = list_create();
+ pr->young_outside_nursery = tree_create();
pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * (i + 1);
highest_overflow_number = pr->overflow_number;
}
@@ -88,6 +89,7 @@
assert(pr->objects_pointing_to_nursery == NULL);
assert(pr->large_overflow_objects == NULL);
list_free(pr->modified_old_objects);
+ tree_free(pr->young_outside_nursery);
}
munmap(stm_object_pages, TOTAL_MEMORY);
diff --git a/c7/test/test_list.py b/c7/test/test_list.py
--- a/c7/test/test_list.py
+++ b/c7/test/test_list.py
@@ -1,3 +1,4 @@
+import random
import cffi
from common import parent_dir
@@ -9,9 +10,11 @@
struct tree_s *tree_create(void);
void tree_free(struct tree_s *tree);
void tree_clear(struct tree_s *tree);
+bool tree_is_cleared(struct tree_s *tree);
bool tree_contains(struct tree_s *tree, uintptr_t addr);
void tree_insert(struct tree_s *tree, uintptr_t addr, uintptr_t val);
bool tree_delete_item(struct tree_s *tree, uintptr_t addr);
+int test_tree_walk(struct tree_s *tree, uintptr_t addrs[]);
""")
lib = ffi.verify('''
@@ -27,6 +30,23 @@
#define _STM_CORE_H_
#include "stm/list.c"
+
+int test_tree_walk(struct tree_s *tree, uintptr_t addrs[])
+{
+ int result = 0;
+ wlog_t *item;
+ TREE_LOOP_FORWARD(*tree, item) {
+ addrs[result++] = item->addr;
+ } TREE_LOOP_END;
+ int i = result;
+ TREE_LOOP_BACKWARD(*tree, item) {
+ assert(i > 0);
+ i--;
+ assert(addrs[i] == item->addr);
+ } TREE_LOOP_END;
+ assert(i == 0);
+ return result;
+}
''', define_macros=[('STM_TESTS', '1')],
undef_macros=['NDEBUG'],
include_dirs=[parent_dir],
@@ -35,6 +55,8 @@
# ____________________________________________________________
+# XXX need tests for list_xxx too
+
def test_tree_empty():
t = lib.tree_create()
for i in range(100):
@@ -47,3 +69,57 @@
for i in range(100):
assert lib.tree_contains(t, i) == (i == 23)
lib.tree_free(t)
+
+def test_tree_is_cleared():
+ t = lib.tree_create()
+ assert lib.tree_is_cleared(t)
+ lib.tree_insert(t, 23, 456)
+ assert not lib.tree_is_cleared(t)
+ lib.tree_free(t)
+
+def test_tree_delete_item():
+ t = lib.tree_create()
+ lib.tree_insert(t, 23, 456)
+ lib.tree_insert(t, 42, 34289)
+ assert not lib.tree_is_cleared(t)
+ assert lib.tree_contains(t, 23)
+ res = lib.tree_delete_item(t, 23)
+ assert res
+ assert not lib.tree_contains(t, 23)
+ res = lib.tree_delete_item(t, 23)
+ assert not res
+ res = lib.tree_delete_item(t, 21)
+ assert not res
+ assert not lib.tree_is_cleared(t)
+ assert lib.tree_contains(t, 42)
+ res = lib.tree_delete_item(t, 42)
+ assert res
+ assert not lib.tree_is_cleared(t) # not cleared, but still empty
+ for i in range(100):
+ assert not lib.tree_contains(t, i)
+ lib.tree_free(t)
+
+def test_tree_walk():
+ t = lib.tree_create()
+ lib.tree_insert(t, 23, 456)
+ lib.tree_insert(t, 42, 34289)
+ a = ffi.new("uintptr_t[10]")
+ res = lib.test_tree_walk(t, a)
+ assert res == 2
+ assert a[0] == 23
+ assert a[1] == 42
+ lib.tree_free(t)
+
+def test_tree_walk_big():
+ t = lib.tree_create()
+ values = [random.randrange(0, 1000000) for i in range(300)]
+ for x in values:
+ lib.tree_insert(t, x, x)
+ a = ffi.new("uintptr_t[1000]")
+ res = lib.test_tree_walk(t, a)
+ assert res == 300
+ found = set()
+ for i in range(res):
+ found.add(a[i])
+ assert found == set(values)
+ lib.tree_free(t)
diff --git a/c7/test/test_nursery.py b/c7/test/test_nursery.py
--- a/c7/test/test_nursery.py
+++ b/c7/test/test_nursery.py
@@ -3,23 +3,6 @@
class TestBasic(BaseTest):
- def test_nursery_large(self):
- py.test.skip("XXX later")
- self.start_transaction()
- lp1 = stm_allocate(SOME_LARGE_SIZE)
- lp2 = stm_allocate(SOME_LARGE_SIZE)
-
- u1 = int(ffi.cast("uintptr_t", lp1))
- u2 = int(ffi.cast("uintptr_t", lp2))
- assert (u1 & 255) == 0
- assert (u2 & 255) == 0
- assert stm_creation_marker(lp1) == 0xff
- assert stm_creation_marker(lp2) == 0xff
-
- self.commit_transaction()
- assert stm_creation_marker(lp1) == 0
- assert stm_creation_marker(lp2) == 0
-
def test_nursery_full(self):
lib._stm_set_nursery_free_count(2048)
self.start_transaction()
@@ -99,7 +82,6 @@
assert young
def test_larger_than_limit_for_nursery(self):
- py.test.skip("XXX later")
obj_size = lib._STM_FAST_ALLOC + 16
self.start_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit