[pypy-commit] stmgc c7-refactor: in-progress
arigo
noreply at buildbot.pypy.org
Fri Feb 14 18:30:32 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r735:35cc44d7afab
Date: 2014-02-14 18:16 +0100
http://bitbucket.org/pypy/stmgc/changeset/35cc44d7afab/
Log: in-progress
diff --git a/c7/stm/atomic.h b/c7/stm/atomic.h
new file mode 100644
--- /dev/null
+++ b/c7/stm/atomic.h
@@ -0,0 +1,12 @@
+
+#if defined(__i386__) || defined(__x86_64__)
+
+# define HAVE_FULL_EXCHANGE_INSN
+ static inline void spin_loop(void) { asm("pause" : : : "memory"); }
+
+#else
+
+# warn "Add a correct definition of spin_loop() for this platform?"
+ static inline void spin_loop(void) { asm("" : : : "memory"); }
+
+#endif
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -3,16 +3,33 @@
#endif
+static uint8_t write_locks[READMARKER_END - READMARKER_START];
+
+
void _stm_write_slowpath(object_t *obj)
{
assert(_running_transaction());
LIST_APPEND(STM_PSEGMENT->old_objects_to_trace, obj);
+ obj->stm_flags |= GCFLAG_WRITE_BARRIER_CALLED;
- obj->stm_flags |= GCFLAG_WRITE_BARRIER_CALLED;
+ /* for old objects from the same transaction, we are done now */
+ if (obj_from_same_transaction(obj))
+ return;
+
+ /* otherwise, we need to privatize the pages containing the object,
+ if they are still SHARED_PAGE. The common case is that there is
+ only one page in total. */
+ if (UNLIKELY((obj->stm_flags & GCFLAG_CROSS_PAGE) != 0)) {
+ abort();
+ //...
+ }
+ else {
+ pages_privatize(((uintptr_t)obj) / 4096UL, 1);
+ }
+
+ //... write_locks
stm_read(obj);
-
- //...
}
static void reset_transaction_read_version(void)
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -6,6 +6,8 @@
#include <sys/mman.h>
#include <errno.h>
+/************************************************************/
+
#define NB_PAGES (1500*256) // 1500MB
#define NB_SEGMENTS 2
@@ -33,17 +35,17 @@
_stm_write_slowpath() is called, and then the flag is set to
say "called once already, no need to call again". */
GCFLAG_WRITE_BARRIER_CALLED = _STM_GCFLAG_WRITE_BARRIER_CALLED,
- /* set if the object can be seen by all threads. If unset, we know
- it is only visible from the current thread. */
- //GCFLAG_ALL_THREADS = 0x04,
- /* only used during collections to mark an obj as moved out of the
- generation it was in */
- //GCFLAG_MOVED = 0x01,
- /* objects smaller than one page and even smaller than
- LARGE_OBJECT_WORDS * 8 bytes */
- //GCFLAG_SMALL = 0x02,
+ /* objects that are allocated crossing a page boundary have this
+ flag set */
+ GCFLAG_CROSS_PAGE = 0x02,
};
+#define CROSS_PAGE_BOUNDARY(start, stop) \
+ (((uintptr_t)(start)) / 4096UL != ((uintptr_t)(stop)) / 4096UL)
+
+
+/************************************************************/
+
#define STM_PSEGMENT ((stm_priv_segment_info_t *)STM_SEGMENT)
@@ -82,3 +84,7 @@
static bool _is_tl_registered(stm_thread_local_t *tl);
static bool _running_transaction(void);
+
+static inline bool obj_from_same_transaction(object_t *obj) {
+ return ((stm_creation_marker_t *)(((uintptr_t)obj) >> 8))->cm != 0;
+}
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -5,17 +5,38 @@
static void setup_gcpage(void)
{
- largemalloc_init_arena(stm_object_pages + END_NURSERY_PAGE * 4096UL,
- (NB_PAGES - END_NURSERY_PAGE) * 4096UL);
+ char *base = stm_object_pages + END_NURSERY_PAGE * 4096UL;
+ uintptr_t length = (NB_PAGES - END_NURSERY_PAGE) * 4096UL;
+ largemalloc_init_arena(base, length);
+
+ uninitialized_page_start = (stm_char *)(END_NURSERY_PAGE * 4096UL);
+ uninitialized_page_stop = (stm_char *)(NB_PAGES * 4096UL);
}
object_t *_stm_allocate_old(ssize_t size_rounded_up)
{
+ /* XXX not thread-safe! */
char *addr = large_malloc(size_rounded_up);
- object_t* o = (object_t *)(addr - stm_object_pages);
+ stm_char* o = (stm_char *)(addr - stm_object_pages);
- long i;
- for (i = 0; i < NB_SEGMENTS; i++)
- memset(REAL_ADDRESS(get_segment_base(i), o), 0, size_rounded_up);
- return o;
+ if (o + size_rounded_up > uninitialized_page_start) {
+ uintptr_t pagenum =
+ ((uint64_t)uninitialized_page_start) / 4096UL;
+ uintptr_t pagecount =
+ (o + size_rounded_up - uninitialized_page_start) / 4096UL + 20;
+ uintptr_t pagemax =
+ (uninitialized_page_stop - uninitialized_page_start) / 4096UL;
+ if (pagecount > pagemax)
+ pagecount = pagemax;
+ pages_initialize_shared(pagenum, pagecount);
+
+ uninitialized_page_start += pagecount * 4096UL;
+ }
+
+ memset(addr, 0, size_rounded_up);
+
+ if (CROSS_PAGE_BOUNDARY(o, o + size_rounded_up))
+ ((object_t *)o)->stm_flags = GCFLAG_CROSS_PAGE;
+
+ return (object_t *)o;
}
diff --git a/c7/stm/gcpage.h b/c7/stm/gcpage.h
new file mode 100644
--- /dev/null
+++ b/c7/stm/gcpage.h
@@ -0,0 +1,3 @@
+
+static stm_char *uninitialized_page_start;
+static stm_char *uninitialized_page_stop;
diff --git a/c7/stm/pages.c b/c7/stm/pages.c
--- a/c7/stm/pages.c
+++ b/c7/stm/pages.c
@@ -19,11 +19,61 @@
abort();
}
}
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++) {
+ assert(flag_page_private[pagenum + i] == FREE_PAGE);
flag_page_private[pagenum + i] = SHARED_PAGE;
+ }
}
static void _pages_privatize(uintptr_t pagenum, uintptr_t count)
{
- abort();
+ assert(count == 1); /* XXX */
+
+#ifdef HAVE_FULL_EXCHANGE_INSN
+ /* use __sync_lock_test_and_set() as a cheaper alternative to
+ __sync_bool_compare_and_swap(). */
+ int previous = __sync_lock_test_and_set(&flag_page_private[pagenum],
+ REMAPPING_PAGE);
+ assert(previous != FREE_PAGE);
+ if (previous == PRIVATE_PAGE) {
+ flag_page_private[pagenum] = PRIVATE_PAGE;
+ return;
+ }
+ bool was_shared = (previous == SHARED_PAGE);
+#else
+ bool was_shared = __sync_bool_compare_and_swap(&flag_page_private[pagenum],
+ SHARED_PAGE, REMAPPING_PAGE);
+#endif
+ if (!was_shared) {
+ while (1) {
+ uint8_t state = ((uint8_t volatile *)flag_page_private)[pagenum];
+ if (state != REMAPPING_PAGE) {
+ assert(state == PRIVATE_PAGE);
+ break;
+ }
+ spin_loop();
+ }
+ return;
+ }
+
+ ssize_t pgoff1 = pagenum;
+ ssize_t pgoff2 = pagenum + NB_PAGES;
+ ssize_t localpgoff = pgoff1 + NB_PAGES * _STM_TL->thread_num;
+ ssize_t otherpgoff = pgoff1 + NB_PAGES * (1 - _STM_TL->thread_num);
+
+ void *localpg = object_pages + localpgoff * 4096UL;
+ void *otherpg = object_pages + otherpgoff * 4096UL;
+
+ // XXX should not use pgoff2, but instead the next unused page in
+ // thread 2, so that after major GCs the next dirty pages are the
+ // same as the old ones
+ int res = remap_file_pages(localpg, 4096, 0, pgoff2, 0);
+ if (res < 0) {
+ perror("remap_file_pages");
+ abort();
+ }
+ pagecopy(localpg, otherpg);
+ write_fence();
+ assert(flag_page_private[pagenum] == REMAPPING_PAGE);
+ flag_page_private[pagenum] = PRIVATE_PAGE;
}
diff --git a/c7/stm/pages.h b/c7/stm/pages.h
--- a/c7/stm/pages.h
+++ b/c7/stm/pages.h
@@ -3,14 +3,14 @@
/* The page is not in use. Assume that each segment sees its own copy. */
FREE_PAGE=0,
- /* The page is shared by all threads. Each segment sees the same
+ /* The page is shared by all segments. Each segment sees the same
physical page (the one that is within the segment 0 mmap address). */
SHARED_PAGE,
/* Page being in the process of privatization */
REMAPPING_PAGE,
- /* Page private for each thread */
+ /* Page is private for each segment. */
PRIVATE_PAGE,
}; /* used for flag_page_private */
@@ -18,7 +18,6 @@
static uint8_t flag_page_private[NB_PAGES];
-
static void _pages_privatize(uintptr_t pagenum, uintptr_t count);
static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
diff --git a/c7/stm/prebuilt.c b/c7/stm/prebuilt.c
--- a/c7/stm/prebuilt.c
+++ b/c7/stm/prebuilt.c
@@ -8,6 +8,8 @@
static uint64_t prebuilt_objects_start = 0;
+/* XXX NOT TESTED, AND NOT WORKING RIGHT NOW */
+
void stm_copy_prebuilt_objects(object_t *target, char *source, ssize_t size)
{
/* Initialize a region of 'size' bytes at the 'target' address,
diff --git a/c7/stmgc.c b/c7/stmgc.c
--- a/c7/stmgc.c
+++ b/c7/stmgc.c
@@ -1,8 +1,10 @@
#define _GNU_SOURCE
#include "stmgc.h"
+#include "stm/atomic.h"
#include "stm/list.h"
#include "stm/core.h"
#include "stm/pages.h"
+#include "stm/gcpage.h"
#include "stm/sync.h"
#include "stm/largemalloc.h"
More information about the pypy-commit
mailing list