Author: Armin Rigo <[email protected]>
Branch: c7-refactor
Changeset: r734:b8d2ad0cb59c
Date: 2014-02-14 17:21 +0100
http://bitbucket.org/pypy/stmgc/changeset/b8d2ad0cb59c/

Log:    in-progress

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -5,7 +5,14 @@
 
 void _stm_write_slowpath(object_t *obj)
 {
-    abort();
+    assert(_running_transaction());
+
+    LIST_APPEND(STM_PSEGMENT->old_objects_to_trace, obj);
+
+    obj->stm_flags |= GCFLAG_WRITE_BARRIER_CALLED;
+    stm_read(obj);
+
+    //...
 }
 
 static void reset_transaction_read_version(void)
@@ -45,6 +52,8 @@
     STM_SEGMENT->transaction_read_version = old_rv + 1;
     if (UNLIKELY(old_rv == 0xff))
         reset_transaction_read_version();
+
+    assert(list_is_empty(STM_PSEGMENT->old_objects_to_trace));
 }
 
 
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -51,11 +51,16 @@
 
 struct stm_priv_segment_info_s {
     struct stm_segment_info_s pub;
+    struct list_s *old_objects_to_trace;
 };
 
 static char *stm_object_pages;
 static stm_thread_local_t *stm_thread_locals = NULL;
 
+#ifdef STM_TESTS
+static char *stm_other_pages;
+#endif
+
 
 #define REAL_ADDRESS(segment_base, src)   ((segment_base) + (uintptr_t)(src))
 
@@ -76,3 +81,4 @@
 }
 
 static bool _is_tl_registered(stm_thread_local_t *tl);
+static bool _running_transaction(void);
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -14,6 +14,8 @@
     char *addr = large_malloc(size_rounded_up);
     object_t* o = (object_t *)(addr - stm_object_pages);
 
-    memset(REAL_ADDRESS(STM_SEGMENT->segment_base, o), 0, size_rounded_up);
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++)
+        memset(REAL_ADDRESS(get_segment_base(i), o), 0, size_rounded_up);
     return o;
 }
diff --git a/c7/stm/list.c b/c7/stm/list.c
new file mode 100644
--- /dev/null
+++ b/c7/stm/list.c
@@ -0,0 +1,33 @@
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+
+#define LIST_SETSIZE(n)    (sizeof(struct list_s) + LIST_ITEMSSIZE(n))
+#define LIST_ITEMSSIZE(n)  ((n) * sizeof(uintptr_t))
+#define LIST_OVERCNT(n)    (33 + ((((n) / 2) * 3) | 1))
+
+static struct list_s *list_create(void)
+{
+    uintptr_t initial_allocation = 32;
+    struct list_s *lst = malloc(LIST_SETSIZE(initial_allocation));
+    if (lst == NULL) {
+        perror("out of memory in list_create");
+        abort();
+    }
+    lst->count = 0;
+    lst->last_allocated = initial_allocation - 1;
+    return lst;
+}
+
+static struct list_s *_list_grow(struct list_s *lst, uintptr_t nalloc)
+{
+    nalloc = LIST_OVERCNT(nalloc);
+    lst = realloc(lst, LIST_SETSIZE(nalloc));
+    if (lst == NULL) {
+        perror("out of memory in _list_grow");
+        abort();
+    }
+    lst->last_allocated = nalloc - 1;
+    return lst;
+}
diff --git a/c7/stm/list.h b/c7/stm/list.h
new file mode 100644
--- /dev/null
+++ b/c7/stm/list.h
@@ -0,0 +1,64 @@
+#include <stdlib.h>
+
+struct list_s {
+    uintptr_t count;
+    uintptr_t last_allocated;
+    uintptr_t items[];
+};
+
+static struct list_s *list_create(void);
+
+static inline void list_free(struct list_s *lst)
+{
+    free(lst);
+}
+
+
+static struct list_s *_list_grow(struct list_s *, uintptr_t);
+
+static inline struct list_s *list_append(struct list_s *lst, uintptr_t item)
+{
+    uintptr_t index = lst->count++;
+    if (UNLIKELY(index > lst->last_allocated))
+        lst = _list_grow(lst, index);
+    lst->items[index] = item;
+    return lst;
+}
+
+#define LIST_APPEND(lst, e)   ((lst) = list_append((lst), (uintptr_t)(e)))
+
+
+static inline void list_clear(struct list_s *lst)
+{
+    lst->count = 0;
+}
+
+static inline bool list_is_empty(struct list_s *lst)
+{
+    return (lst->count == 0);
+}
+
+static inline bool list_count(struct list_s *lst)
+{
+    return lst->count;
+}
+
+static inline uintptr_t list_pop_item(struct list_s *lst)
+{
+    return lst->items[--lst->count];
+}
+
+static inline uintptr_t list_item(struct list_s *lst, uintptr_t index)
+{
+    return lst->items[index];
+}
+
+#define LIST_FOREACH_R(lst, TYPE, CODE)         \
+    do {                                        \
+        struct list_s *_lst = (lst);            \
+        uintptr_t _i;                           \
+        for (_i = _lst->count; _i--; ) {        \
+            TYPE item = (TYPE)_lst->items[_i];  \
+            CODE;                               \
+        }                                       \
+    } while (0)
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -39,6 +39,9 @@
     long i;
     for (i = 0; i < NB_SEGMENTS; i++) {
         char *segment_base = get_segment_base(i);
+#ifdef STM_TESTS
+        stm_other_pages = segment_base;
+#endif
 
         /* In each segment, the first page is where TLPREFIX'ed
            NULL accesses land.  We mprotect it so that accesses fail. */
@@ -59,6 +62,7 @@
         struct stm_priv_segment_info_s *pr = get_priv_segment(i);
         pr->pub.segment_num = i;
         pr->pub.segment_base = segment_base;
+        pr->old_objects_to_trace = list_create();
     }
 
     /* Make the nursery pages shared.  The other pages are
@@ -85,6 +89,12 @@
 {
     /* This function is called during testing, but normal programs don't
        need to call it. */
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        struct stm_priv_segment_info_s *pr = get_priv_segment(i);
+        list_free(pr->old_objects_to_trace);
+    }
+
     munmap(stm_object_pages, TOTAL_MEMORY);
     stm_object_pages = NULL;
 
diff --git a/c7/stm/sync.c b/c7/stm/sync.c
--- a/c7/stm/sync.c
+++ b/c7/stm/sync.c
@@ -81,6 +81,11 @@
     sem_post(&segments_ctl.semaphore);
 }
 
+static bool _running_transaction(void)
+{
+    return (STM_SEGMENT->running_thread != NULL);
+}
+
 bool _stm_in_transaction(stm_thread_local_t *tl)
 {
     int num = tl->associated_segment_num;
diff --git a/c7/stmgc.c b/c7/stmgc.c
--- a/c7/stmgc.c
+++ b/c7/stmgc.c
@@ -1,11 +1,13 @@
 #define _GNU_SOURCE
 #include "stmgc.h"
+#include "stm/list.h"
 #include "stm/core.h"
 #include "stm/pages.h"
 #include "stm/sync.h"
 #include "stm/largemalloc.h"
 
 #include "stm/misc.c"
+#include "stm/list.c"
 #include "stm/pages.c"
 #include "stm/prebuilt.c"
 #include "stm/gcpage.c"
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -35,6 +35,7 @@
 
 typedef struct {
     object_t **shadowstack, **shadowstack_base;
+    int associated_segment_num;
     ...;
 } stm_thread_local_t;
 
@@ -339,7 +340,7 @@
 
 def stm_get_real_address(obj):
     return lib._stm_real_address(ffi.cast('object_t*', obj))
-    
+
 def stm_get_segment_address(ptr):
     return int(ffi.cast('uintptr_t', lib._stm_segment_address(ptr)))
 
@@ -423,6 +424,12 @@
         assert not lib._stm_in_transaction(tl)
         lib._stm_start_transaction(tl, ffi.cast("stm_jmpbuf_t *", -1))
         assert lib._stm_in_transaction(tl)
+        #
+        seen = set()
+        for tl1 in self.tls:
+            if lib._stm_in_transaction(tl1):
+                assert tl1.associated_segment_num not in seen
+                seen.add(tl1.associated_segment_num)
 
     def commit_transaction(self):
         tl = self.tls[self.current_thread]
diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py
--- a/c7/test/test_basic.py
+++ b/c7/test/test_basic.py
@@ -61,13 +61,16 @@
     def test_write_on_old(self):
         lp1 = stm_allocate_old(16)
         self.start_transaction()
+        assert stm_get_char(lp1) == '\0'
         stm_write(lp1)
         assert stm_was_written(lp1)
         stm_set_char(lp1, 'a')
+        assert stm_get_char(lp1) == 'a'
 
         self.switch(1)
         self.start_transaction()
-        stm_read(lp1)
+        assert not stm_was_read(lp1)
+        assert stm_get_char(lp1) == '\0'
         assert stm_was_read(lp1)
         assert stm_get_char(lp1) == '\0'
         self.commit_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to