[pypy-commit] stmgc default: Start importing "c3/gcpage".

arigo noreply at buildbot.pypy.org
Mon Jun 17 13:35:51 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r165:04275ee055bf
Date: 2013-06-17 13:18 +0200
http://bitbucket.org/pypy/stmgc/changeset/04275ee055bf/

Log:	Start importing "c3/gcpage".

diff --git a/c4/Makefile b/c4/Makefile
--- a/c4/Makefile
+++ b/c4/Makefile
@@ -9,8 +9,11 @@
 
 
 H_FILES = atomic_ops.h stmgc.h stmimpl.h \
-	  et.h lists.h steal.h nursery.h stmsync.h dbgmem.h fprintcolor.h
-C_FILES = et.c lists.c steal.c nursery.c stmsync.c dbgmem.c fprintcolor.c
+	  et.h lists.h steal.h nursery.h gcpage.h \
+          stmsync.h dbgmem.h fprintcolor.h
+
+C_FILES = et.c lists.c steal.c nursery.c gcpage.c \
+          stmsync.c dbgmem.c fprintcolor.c
 
 DEBUG = -g -DGC_NURSERY=0x10000  #-D_GC_DEBUG=1
 
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -13,7 +13,6 @@
 
 #define MAX_THREADS         1024
 #define LOCKED              (INTPTR_MAX - 2*(MAX_THREADS-1))
-#define WORD                sizeof(gcptr)
 
 /* Description of the flags
  * ------------------------
@@ -119,7 +118,8 @@
   struct GcPtrList stolen_objects;
   struct GcPtrList stolen_young_stubs;
   revision_t free_list_next;
-  /* xxx gcpage data here */
+
+  GCPAGE_FIELDS_DECL
 };
 
 /* this struct contains all thread-local data that is never accessed
diff --git a/c4/gcpage.c b/c4/gcpage.c
new file mode 100644
--- /dev/null
+++ b/c4/gcpage.c
@@ -0,0 +1,15 @@
+#include "stmimpl.h"
+
+
+/* For statistics */
+static uintptr_t count_global_pages;
+
+/* For tests */
+long stmgcpage_count(int quantity)
+{
+    switch (quantity) {
+    case 0: return count_global_pages;
+    case 1: return LOCAL_GCPAGES()->count_pages;
+    default: return -1;
+    }
+}
diff --git a/c4/gcpage.h b/c4/gcpage.h
new file mode 100644
--- /dev/null
+++ b/c4/gcpage.h
@@ -0,0 +1,78 @@
+#ifndef _SRCSTM_GCPAGE_H
+#define _SRCSTM_GCPAGE_H
+
+
+#define WORD                sizeof(gcptr)
+#define GC_SMALL_REQUESTS   36
+
+#define DEBUG_WORD(char)    (revision_t)(((char) *                      \
+                                      (WORD >= 8 ? 0x0101010101010101ULL \
+                                                 : 0x01010101ULL)))
+
+
+/* Linux's glibc is good at 'malloc(1023*WORD)': the blocks ("pages") it
+   returns are exactly 1024 words apart, reserving only one extra word
+   for its internal data.  Here we assume that even on other systems it
+   will not use more than three words. */
+#ifndef GC_PAGE_SIZE
+#define GC_PAGE_SIZE   (1021 * WORD)
+#endif
+
+/* This is the largest size that we will map to our internal "pages"
+   structures. */
+#define GC_SMALL_REQUEST_THRESHOLD   ((GC_SMALL_REQUESTS-1) * WORD)
+
+/* The minimum heap size: never run a full collection with a smaller heap. */
+#ifndef GC_MIN
+#define GC_MIN    (16 * 1024 * 1024)
+#endif
+
+/* The minimum expansion factor: never run a full collection before we have
+   allocated this much space. */
+#ifndef GC_EXPAND
+#define GC_EXPAND    (7 * 1024 * 1024)
+#endif
+
+/* The heap is collected when it reaches 1.82 times what it had before. */
+#define GC_MAJOR_COLLECT    1.82
+
+
+typedef struct page_header_s {
+    struct page_header_s *next_page;
+} page_header_t;
+
+
+/* These fields are in tx_public_descriptor rather than tx_descriptor.
+   The indirection allows us to keep around the lists of pages even
+   after the thread finishes, until the next major collection.
+*/
+#define GCPAGE_FIELDS_DECL                                              \
+    /* The array 'pages_for_size' contains GC_SMALL_REQUESTS            \
+       chained lists of pages currently managed by this thread.         \
+       For each size N between WORD and SMALL_REQUEST_THRESHOLD         \
+       (included), the corresponding chained list contains pages        \
+       which store objects of size N. */                                \
+    struct page_header_s *pages_for_size[GC_SMALL_REQUESTS];            \
+                                                                        \
+    /* This array contains GC_SMALL_REQUESTS chained lists of           \
+       free locations. */                                               \
+    gcptr free_loc_for_size[GC_SMALL_REQUESTS];                         \
+                                                                        \
+    /* For statistics */                                                \
+    uintptr_t count_pages;
+
+
+#define LOCAL_GCPAGES()  (thread_descriptor->public_descriptor)
+
+
+void stmgcpage_init_tls(void);
+void stmgcpage_done_tls(void);
+gcptr stmgcpage_malloc(size_t size);
+void stmgcpage_free(gcptr obj);
+void stmgcpage_add_prebuilt_root(gcptr obj);
+void stmgcpage_possibly_major_collect(int force);
+long stmgcpage_count(int quantity);
+
+extern struct GcPtrList stm_prebuilt_gcroots;
+
+#endif
diff --git a/c4/stmimpl.h b/c4/stmimpl.h
--- a/c4/stmimpl.h
+++ b/c4/stmimpl.h
@@ -30,6 +30,7 @@
 #include "fprintcolor.h"
 #include "lists.h"
 #include "dbgmem.h"
+#include "gcpage.h"
 #include "nursery.h"
 #include "et.h"
 #include "steal.h"
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -5,11 +5,11 @@
 parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 header_files = [os.path.join(parent_dir, _n) for _n in
-                "et.h lists.h steal.h nursery.h "
+                "et.h lists.h steal.h nursery.h gcpage.h "
                 "stmsync.h dbgmem.h fprintcolor.h "
                 "stmgc.h stmimpl.h atomic_ops.h".split()]
 source_files = [os.path.join(parent_dir, _n) for _n in
-                "et.c lists.c steal.c nursery.c "
+                "et.c lists.c steal.c nursery.c gcpage.c "
                 "stmsync.c dbgmem.c fprintcolor.c".split()]
 
 _pycache_ = os.path.join(parent_dir, 'test', '__pycache__')
@@ -57,7 +57,7 @@
     void *stm_malloc(size_t size);
     //gcptr stmgcpage_malloc(size_t size);
     //void stmgcpage_free(gcptr obj);
-    //long stmgcpage_count(int quantity);
+    long stmgcpage_count(int quantity);
     //void stmgcpage_possibly_major_collect(int);
     revision_t stm_global_cur_time(void);
     //void stmgcpage_add_prebuilt_root(gcptr);
@@ -116,7 +116,6 @@
 
     //extern gcptr stmgcpage_malloc(size_t size);
     //extern void stmgcpage_free(gcptr obj);
-    //extern long stmgcpage_count(int quantity);
     //extern void stmgcpage_possibly_major_collect(int);
     extern revision_t stm_global_cur_time(void);
     //extern void stmgcpage_add_prebuilt_root(gcptr);
diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py
new file mode 100644
--- /dev/null
+++ b/c4/test/test_gcpage.py
@@ -0,0 +1,34 @@
+import py
+from support import *
+
+
+def setup_function(f):
+    lib.stm_clear_between_tests()
+    lib.stm_initialize_tests(getattr(f, 'max_aborts', 0))
+
+def teardown_function(_):
+    lib.stm_finalize()
+
+
+def test_HDR():
+    import struct
+    assert HDR == struct.calcsize("PP")
+
+def test_malloc_simple():
+    assert count_pages() == 0
+    p1 = lib.stmgcpage_malloc(HDR)
+    print p1
+    p2 = lib.stmgcpage_malloc(HDR)
+    print p2
+    p3 = lib.stmgcpage_malloc(HDR)
+    print p3
+    assert count_pages() == 1
+    p4 = lib.stmgcpage_malloc(HDR + 1)
+    print p4
+    assert count_pages() == 2
+    p5 = lib.stmgcpage_malloc(HDR + 1)
+    print p5
+    assert distance(p1, p2) == HDR
+    assert distance(p2, p3) == HDR
+    assert abs(distance(p3, p4)) > PAGE_ROOM / 2
+    assert distance(p4, p5) == HDR + WORD


More information about the pypy-commit mailing list