[pypy-commit] stmgc c7: move some more code
Remi Meier
noreply at buildbot.pypy.org
Wed Jan 22 14:41:33 CET 2014
Author: Remi Meier
Branch: c7
Changeset: r666:4fb6332ddf82
Date: 2014-01-22 14:24 +0100
http://bitbucket.org/pypy/stmgc/changeset/4fb6332ddf82/
Log: move some more code
diff --git a/c7/core.c b/c7/core.c
--- a/c7/core.c
+++ b/c7/core.c
@@ -12,43 +12,17 @@
#include "core.h"
#include "list.h"
-#include "pagecopy.h"
#include "reader_writer_lock.h"
#include "nursery.h"
#include "pages.h"
-#if defined(__i386__) || defined(__x86_64__)
-# define HAVE_FULL_EXCHANGE_INSN
-#endif
-
-
-
char *object_pages;
static int num_threads_started;
uint8_t write_locks[READMARKER_END - READMARKER_START];
-/************************************************************/
-
-
-static void spin_loop(void)
-{
- asm("pause" : : : "memory");
-}
-
-
-static void write_fence(void)
-{
-#if defined(__amd64__) || defined(__i386__)
- asm("" : : : "memory");
-#else
-# error "Define write_fence() for your architecture"
-#endif
-}
-
-/************************************************************/
/* a multi-reader, single-writer lock: transactions normally take a reader
@@ -116,63 +90,6 @@
-static void _stm_privatize(uintptr_t pagenum)
-{
- if (flag_page_private[pagenum] == PRIVATE_PAGE)
- return;
-
-#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);
- 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;
-}
-
-
-
-
-
char *_stm_real_address(object_t *o)
{
@@ -244,17 +161,18 @@
/* for old objects from the same transaction we don't need
to privatize the page */
- if ((flag_page_private[pagenum] == UNCOMMITTED_SHARED_PAGE)
+ if ((stm_get_page_flag(pagenum) == UNCOMMITTED_SHARED_PAGE)
|| (obj->stm_flags & GCFLAG_NOT_COMMITTED)) {
obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
return;
}
/* privatize if SHARED_PAGE */
- /* xxx stmcb_size() is probably too slow */
+ /* xxx stmcb_size() is probably too slow, maybe add a GCFLAG_LARGE for
+ objs with more than 1 page */
int pages = stmcb_size(real_address(obj)) / 4096;
for (; pages >= 0; pages--)
- _stm_privatize(pagenum + pages);
+ stm_pages_privatize(pagenum + pages);
/* claim the write-lock for this object */
uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - READMARKER_START;
@@ -341,7 +259,7 @@
}
for (i = FIRST_NURSERY_PAGE; i < FIRST_AFTER_NURSERY_PAGE; i++)
- flag_page_private[i] = PRIVATE_PAGE; /* nursery is private.
+ stm_set_page_flag(i, PRIVATE_PAGE); /* nursery is private.
or should it be UNCOMMITTED??? */
num_threads_started = 0;
@@ -407,7 +325,7 @@
void _stm_teardown(void)
{
munmap(object_pages, TOTAL_MEMORY);
- memset(flag_page_private, 0, sizeof(flag_page_private));
+ _stm_reset_page_flags();
memset(write_locks, 0, sizeof(write_locks));
object_pages = NULL;
}
diff --git a/c7/core.h b/c7/core.h
--- a/c7/core.h
+++ b/c7/core.h
@@ -138,8 +138,24 @@
return object_pages + thread_num * (NB_PAGES * 4096UL);
}
+static inline void spin_loop(void)
+{
+ asm("pause" : : : "memory");
+}
+
+
+static inline void write_fence(void)
+{
+#if defined(__amd64__) || defined(__i386__)
+ asm("" : : : "memory");
+#else
+# error "Define write_fence() for your architecture"
+#endif
+}
+
/* ==================== API ==================== */
+
static inline void stm_read(object_t *obj)
{
((read_marker_t *)(((uintptr_t)obj) >> 4))->rm =
diff --git a/c7/nursery.c b/c7/nursery.c
--- a/c7/nursery.c
+++ b/c7/nursery.c
@@ -32,7 +32,7 @@
void mark_page_as_uncommitted(uintptr_t pagenum)
{
- flag_page_private[pagenum] = UNCOMMITTED_SHARED_PAGE;
+ stm_set_page_flag(pagenum, UNCOMMITTED_SHARED_PAGE);
LIST_APPEND(_STM_TL->uncommitted_pages, (object_t*)pagenum);
}
@@ -253,7 +253,7 @@
item->stm_flags &= ~GCFLAG_NOT_COMMITTED;
uintptr_t pagenum = ((uintptr_t)item) / 4096UL;
- if (flag_page_private[pagenum] == PRIVATE_PAGE) {
+ if (stm_get_page_flag(pagenum) == PRIVATE_PAGE) {
/* page was privatized... */
char *src = REAL_ADDRESS(local_base, item);
char *dst = REAL_ADDRESS(remote_base, item);
@@ -293,7 +293,7 @@
reset in case of an abort */
uintptr_t pagenum = ((uintptr_t)(alloc->next - 1)) / 4096UL;
- if (flag_page_private[pagenum] == UNCOMMITTED_SHARED_PAGE) {
+ if (stm_get_page_flag(pagenum) == UNCOMMITTED_SHARED_PAGE) {
/* becomes a SHARED (done below) partially used page */
alloc->flag_partial_page = 1;
}
@@ -303,7 +303,7 @@
_STM_TL->uncommitted_pages,
({
uintptr_t pagenum = (uintptr_t)item;
- flag_page_private[pagenum] = SHARED_PAGE;
+ stm_set_page_flag(pagenum, SHARED_PAGE);
}));
stm_list_clear(_STM_TL->uncommitted_pages);
}
diff --git a/c7/pages.c b/c7/pages.c
--- a/c7/pages.c
+++ b/c7/pages.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -13,16 +14,89 @@
#include "core.h"
#include "list.h"
#include "pages.h"
+#include "pagecopy.h"
+
+
+#if defined(__i386__) || defined(__x86_64__)
+# define HAVE_FULL_EXCHANGE_INSN
+#endif
+
+
uint8_t flag_page_private[NB_PAGES];
uintptr_t index_page_never_used;
+void _stm_reset_page_flags()
+{
+ memset(flag_page_private, 0, sizeof(flag_page_private));
+}
-uint8_t _stm_get_page_flag(int pagenum)
+uint8_t stm_get_page_flag(int pagenum)
{
return flag_page_private[pagenum];
}
+void stm_set_page_flag(int pagenum, uint8_t flag)
+{
+ assert(flag_page_private[pagenum] != flag);
+ flag_page_private[pagenum] = flag;
+}
+
+
+
+void stm_pages_privatize(uintptr_t pagenum)
+{
+ if (flag_page_private[pagenum] == PRIVATE_PAGE)
+ return;
+
+#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);
+ 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;
+}
+
uintptr_t stm_pages_reserve(int num)
{
diff --git a/c7/pages.h b/c7/pages.h
--- a/c7/pages.h
+++ b/c7/pages.h
@@ -15,9 +15,12 @@
}; /* flag_page_private */
+void stm_pages_privatize(uintptr_t pagenum);
uintptr_t stm_pages_reserve(int num);
-uint8_t _stm_get_page_flag(int pagenum);
+uint8_t stm_get_page_flag(int pagenum);
+void stm_set_page_flag(int pagenum, uint8_t flag);
+void _stm_reset_page_flags(void);
-extern uint8_t flag_page_private[NB_PAGES];
+
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -79,7 +79,7 @@
extern void stmcb_trace(struct object_s *, void (object_t **));
uint8_t _stm_get_flags(object_t *obj);
-uint8_t _stm_get_page_flag(int pagenum);
+uint8_t stm_get_page_flag(int pagenum);
enum {
SHARED_PAGE=0,
REMAPPING_PAGE,
@@ -337,7 +337,7 @@
lib._stm_minor_collect()
def stm_get_page_flag(pagenum):
- return lib._stm_get_page_flag(pagenum)
+ return lib.stm_get_page_flag(pagenum)
def stm_get_obj_size(o):
return lib.stmcb_size(stm_get_real_address(o))
More information about the pypy-commit
mailing list