[pypy-commit] stmgc default: remove size parameter in stm_free and introduce new _GC_MEMPROTECT define to enable the use of mprotect to find invalid accesses

Raemi noreply at buildbot.pypy.org
Fri Aug 30 15:13:13 CEST 2013


Author: Remi Meier <remi.meier at gmail.com>
Branch: 
Changeset: r503:0f8f97c25ca8
Date: 2013-08-30 15:13 +0200
http://bitbucket.org/pypy/stmgc/changeset/0f8f97c25ca8/

Log:	remove size parameter in stm_free and introduce new _GC_MEMPROTECT
	define to enable the use of mprotect to find invalid accesses

diff --git a/c4/Makefile b/c4/Makefile
--- a/c4/Makefile
+++ b/c4/Makefile
@@ -21,7 +21,7 @@
 C_FILES = et.c lists.c steal.c nursery.c gcpage.c \
           stmsync.c extra.c weakref.c dbgmem.c fprintcolor.c
 
-DEBUG = -g -DGC_NURSERY=0x10000 -D_GC_DEBUG=1 -DDUMP_EXTRA=1 -D_GC_DEBUGPRINTS=1 -DSTM_BARRIER_COUNT=1
+DEBUG = -g -DGC_NURSERY=0x10000 -D_GC_DEBUG=1 -DDUMP_EXTRA=1 -D_GC_DEBUGPRINTS=1 -DSTM_BARRIER_COUNT=1 -D_GC_MEMPROTECT
 
 
 # note that we don't say -DNDEBUG, so that asserts should still be compiled in
diff --git a/c4/dbgmem.c b/c4/dbgmem.c
--- a/c4/dbgmem.c
+++ b/c4/dbgmem.c
@@ -3,12 +3,12 @@
 
 
 #define PAGE_SIZE  4096
-
+#define MEM_SIZE(mem) (*(((size_t *)(mem)) - 1))
 
 #ifdef _GC_DEBUG
 /************************************************************/
 
-#define MMAP_TOTAL  1280*1024*1024   /* 1280MB */
+#define MMAP_TOTAL  2000*1024*1024   /* 2000MB */
 
 static pthread_mutex_t malloc_mutex = PTHREAD_MUTEX_INITIALIZER;
 static char *zone_start, *zone_current = NULL, *zone_end = NULL;
@@ -31,6 +31,7 @@
 
 void *stm_malloc(size_t sz)
 {
+    size_t real_sz = sz + sizeof(size_t);
     pthread_mutex_lock(&malloc_mutex);
 
     if (zone_current == NULL) {
@@ -42,10 +43,14 @@
         zone_current = zone_start;
         zone_end = zone_start + MMAP_TOTAL;
         assert((MMAP_TOTAL % PAGE_SIZE) == 0);
+#ifdef _GC_MEMPROTECT
         _stm_dbgmem(zone_start, MMAP_TOTAL, PROT_NONE);
+#else
+        _stm_dbgmem(zone_start, MMAP_TOTAL, PROT_READ | PROT_WRITE);
+#endif
     }
 
-    size_t nb_pages = (sz + PAGE_SIZE - 1) / PAGE_SIZE + 1;
+    size_t nb_pages = (real_sz + PAGE_SIZE - 1) / PAGE_SIZE + 1;
     char *result = zone_current;
     zone_current += nb_pages * PAGE_SIZE;
     if (zone_current > zone_end) {
@@ -54,50 +59,61 @@
     }
     pthread_mutex_unlock(&malloc_mutex);
 
-    result += (-sz) & (PAGE_SIZE-1);
-    assert(((intptr_t)(result + sz) & (PAGE_SIZE-1)) == 0);
-    _stm_dbgmem(result, sz, PROT_READ | PROT_WRITE);
+    result += (-real_sz) & (PAGE_SIZE-1);
+    assert(((intptr_t)(result + real_sz) & (PAGE_SIZE-1)) == 0);
+#ifdef _GC_MEMPROTECT
+    _stm_dbgmem(result, real_sz, PROT_READ | PROT_WRITE);
+#endif
 
     long i, base = (result - zone_start) / PAGE_SIZE;
     for (i = 0; i < nb_pages; i++)
         accessible_pages[base + i] = 42;
 
     dprintf(("stm_malloc(%zu): %p\n", sz, result));
-    assert(((intptr_t)(result + sz) & (PAGE_SIZE-1)) == 0);
-    memset(result, 0xBB, sz);
+    assert(((intptr_t)(result + real_sz) & (PAGE_SIZE-1)) == 0);
+    memset(result, 0xBB, real_sz);
+    
+    result += sizeof(size_t);
+    MEM_SIZE(result) = real_sz;
     return result;
 }
 
-void stm_free(void *p, size_t sz)
+void stm_free(void *p)
 {
     if (p == NULL) {
-        assert(sz == 0);
         return;
     }
-    assert(((intptr_t)((char *)p + sz) & (PAGE_SIZE-1)) == 0);
+    size_t real_sz = MEM_SIZE(p);
+    void *real_p = p - sizeof(size_t);
+    assert(real_sz > 0);
 
-    size_t nb_pages = (sz + PAGE_SIZE - 1) / PAGE_SIZE + 1;
-    long i, base = ((char *)p - zone_start) / PAGE_SIZE;
+    assert(((intptr_t)((char *)real_p + real_sz) & (PAGE_SIZE-1)) == 0);
+
+    size_t nb_pages = (real_sz + PAGE_SIZE - 1) / PAGE_SIZE + 1;
+    long i, base = ((char *)real_p - zone_start) / PAGE_SIZE;
     assert(0 <= base && base < (MMAP_TOTAL / PAGE_SIZE));
     for (i = 0; i < nb_pages; i++) {
         assert(accessible_pages[base + i] == 42);
         accessible_pages[base + i] = -1;
     }
-    memset(p, 0xDD, sz);
-    _stm_dbgmem(p, sz, PROT_NONE);
+    memset(real_p, 0xDD, real_sz);
+#ifdef _GC_MEMPROTECT
+    _stm_dbgmem(real_p, real_sz, PROT_NONE);
+#endif
 }
 
 void *stm_realloc(void *p, size_t newsz, size_t oldsz)
 {
     void *r = stm_malloc(newsz);
     memcpy(r, p, oldsz < newsz ? oldsz : newsz);
-    stm_free(p, oldsz);
+    stm_free(p);
     return r;
 }
 
 int _stm_can_access_memory(char *p)
 {
-    long base = ((char *)p - zone_start) / PAGE_SIZE;
+    char* real_p = p - sizeof(size_t);
+    long base = ((char *)real_p - zone_start) / PAGE_SIZE;
     assert(0 <= base && base < (MMAP_TOTAL / PAGE_SIZE));
     return accessible_pages[base] == 42;
 }
diff --git a/c4/dbgmem.h b/c4/dbgmem.h
--- a/c4/dbgmem.h
+++ b/c4/dbgmem.h
@@ -5,7 +5,7 @@
 #ifdef _GC_DEBUG
 
 void *stm_malloc(size_t);
-void stm_free(void *, size_t);
+void stm_free(void *);
 void *stm_realloc(void *, size_t, size_t);
 int _stm_can_access_memory(char *);
 void assert_cleared(char *, size_t);
@@ -13,7 +13,7 @@
 #else
 
 #define stm_malloc(sz)    malloc(sz)
-#define stm_free(p,sz)    free(p)
+#define stm_free(p)    free(p)
 #define stm_realloc(p,newsz,oldsz)  realloc(p,newsz)
 #define assert_cleared(p,sz)     do { } while(0)
 
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -1746,5 +1746,5 @@
     p += sprintf(p, "]\n");
     dprintf(("%s", line));
 
-    stm_free(d, sizeof(struct tx_descriptor));
+    stm_free(d);
 }
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -41,7 +41,8 @@
         stm_minor_collect();
         obj = stm_pop_root();
     }
-    
+    assert(obj->h_tid & GCFLAG_OLD);
+
     spinlock_acquire(d->public_descriptor->collection_lock, 'P');
 
     stub = stm_stub_malloc(d->public_descriptor, 0);
@@ -57,8 +58,6 @@
         stub->h_original = (revision_t)obj;
     }
 
-    STUB_THREAD(stub) = d->public_descriptor;
-
     result = (intptr_t)stub;
     spinlock_release(d->public_descriptor->collection_lock);
     stm_register_integer_address(result);
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -208,7 +208,7 @@
     }
     else {
         g2l_delete_item(&gcp->nonsmall_objects, obj);
-        stm_free(obj, size);
+        stm_free(obj);
     }
 }
 
@@ -500,6 +500,7 @@
     G2L_LOOP_FORWARD(registered_stubs, item) {
         gcptr R = item->addr;
         assert(R->h_tid & GCFLAG_SMALLSTUB);
+        assert(!(R->h_tid & (GCFLAG_VISITED | GCFLAG_MARKED)));
 
         R->h_tid |= (GCFLAG_MARKED | GCFLAG_VISITED);
 
@@ -817,7 +818,7 @@
                 p = (gcptr)(((char *)p) + obj_size);
             }
 #endif
-            stm_free(lpage, GC_PAGE_SIZE);
+            stm_free(lpage);
             assert(gcp->count_pages > 0);
             assert(count_global_pages > 0);
             gcp->count_pages--;
@@ -847,7 +848,7 @@
         }
         else {
             G2L_LOOP_DELETE(item);
-            stm_free(p, stmgc_size(p));
+            stm_free(p);
         }
 
     } G2L_LOOP_END_AND_COMPRESS;
diff --git a/c4/lists.c b/c4/lists.c
--- a/c4/lists.c
+++ b/c4/lists.c
@@ -18,7 +18,7 @@
 
 void g2l_delete(struct G2L *g2l)
 {
-  stm_free(g2l->raw_start, g2l->raw_end - g2l->raw_start);
+  stm_free(g2l->raw_start);
   memset(g2l, 0, sizeof(struct G2L));
 }
 
@@ -65,7 +65,7 @@
     {
       g2l_insert(&newg2l, item->addr, item->val);
     } G2L_LOOP_END;
-  stm_free(g2l->raw_start, g2l->raw_end - g2l->raw_start);
+  stm_free(g2l->raw_start);
   *g2l = newg2l;
 }
 
@@ -151,7 +151,7 @@
     //fprintf(stderr, "list %p deleted (%ld KB)\n",
     //gcptrlist, gcptrlist->alloc * sizeof(gcptr) / 1024);
   gcptrlist->size = 0;
-  stm_free(gcptrlist->items, gcptrlist->alloc * sizeof(gcptr));
+  stm_free(gcptrlist->items);
   gcptrlist->items = NULL;
   gcptrlist->alloc = 0;
 }
@@ -182,7 +182,7 @@
   long i;
   for (i=0; i<gcptrlist->size; i++)
     newitems[i] = gcptrlist->items[i];
-  stm_free(gcptrlist->items, gcptrlist->alloc * sizeof(gcptr));
+  stm_free(gcptrlist->items);
   gcptrlist->items = newitems;
   gcptrlist->alloc = newalloc;
 }
diff --git a/c4/lists.h b/c4/lists.h
--- a/c4/lists.h
+++ b/c4/lists.h
@@ -38,7 +38,7 @@
 void g2l_clear(struct G2L *g2l);
 void g2l_delete(struct G2L *g2l);
 static inline void g2l_delete_not_used_any_more(struct G2L *g2l) {
-    stm_free(g2l->raw_start, g2l->raw_end - g2l->raw_start);
+    stm_free(g2l->raw_start);
 }
 
 static inline int g2l_any_entry(struct G2L *g2l) {
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -49,7 +49,7 @@
        updatechainheads() -> stub_malloc() -> ...): */
     assert(!minor_collect_anything_to_do(d)
            || d->nursery_current == d->nursery_end);
-    stm_free(d->nursery_base, GC_NURSERY);
+    stm_free(d->nursery_base);
 
     gcptrlist_delete(&d->old_objects_to_trace);
     gcptrlist_delete(&d->public_with_young_copy);
@@ -523,7 +523,7 @@
 #if defined(_GC_DEBUG) && _GC_DEBUG >= 2
     if (d->nursery_cleared == NC_ALREADY_CLEARED)
         assert_cleared(d->nursery_base, GC_NURSERY);
-    stm_free(d->nursery_base, GC_NURSERY);
+    stm_free(d->nursery_base);
     d->nursery_base = stm_malloc(GC_NURSERY);
     d->nursery_end = d->nursery_base + GC_NURSERY;
     dprintf(("minor: nursery moved to [%p to %p]\n", d->nursery_base,
diff --git a/c4/stmsync.c b/c4/stmsync.c
--- a/c4/stmsync.c
+++ b/c4/stmsync.c
@@ -68,7 +68,7 @@
     assert(x == END_MARKER_ON);
     assert(stm_shadowstack == d->shadowstack);
     stm_shadowstack = NULL;
-    stm_free(d->shadowstack, sizeof(gcptr) * LENGTH_SHADOW_STACK);
+    stm_free(d->shadowstack);
 }
 
 void stm_set_max_aborts(int max_aborts)
diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py
--- a/c4/test/test_gcpage.py
+++ b/c4/test/test_gcpage.py
@@ -593,3 +593,34 @@
     assert p1b.h_original == p1org
     assert classify(p1b) == "stub"
     assert lib.getlong(p1, 0) == -8922908
+
+
+def test_copy_stub_over_prebuilt():
+    p = palloc(HDR + WORD)
+    def f1(r):
+        p1 = lib.stm_read_barrier(p)
+        #lib.stm_push_root(p1)
+        r.set(1)
+        r.wait(2)
+        p1n = p1#lib.stm_pop_root()
+        assert p1n.h_tid & GCFLAG_STUB
+        
+    def f2(r):
+        r.wait(1)
+        pw = lib.stm_write_barrier(p)
+        lib.stm_commit_transaction()
+        lib.stm_begin_inevitable_transaction()
+        assert classify(follow_revision(p)) == "stub"
+        
+        lib.stm_push_root(pw)
+        major_collect()
+        pw = lib.stm_pop_root()
+
+        assert p.h_tid & GCFLAG_STUB
+        
+        r.set(2)
+    run_parallel(f1, f2)
+
+    
+
+    


More information about the pypy-commit mailing list