Author: Armin Rigo <[email protected]>
Branch: c5
Changeset: r584:595f211e4f53
Date: 2013-12-23 12:06 +0100
http://bitbucket.org/pypy/stmgc/changeset/595f211e4f53/
Log: in-progress
diff --git a/c5/Makefile b/c5/Makefile
--- a/c5/Makefile
+++ b/c5/Makefile
@@ -2,11 +2,11 @@
H_FILES = core.h pagecopy.h
C_FILES = core.c pagecopy.c
-CLANG = clang -Wall -ferror-limit=3 -fno-color-diagnostics
+CLANG = clang -Wall -ferror-limit=3 -fno-color-diagnostics -fno-exceptions
demo1: demo1.c $(C_FILES) $(H_FILES)
- $(CLANG) -pthread -o $@ -O2 -g demo1.c $(C_FILES)
+ $(CLANG) -pthread -o $@ -O0 -g demo1.c $(C_FILES)
demo2: demo2.c largemalloc.c largemalloc.h
$(CLANG) -o $@ -g demo2.c largemalloc.c
diff --git a/c5/core.c b/c5/core.c
--- a/c5/core.c
+++ b/c5/core.c
@@ -109,7 +109,7 @@
total address space available is huge.
*/
-#define NB_PAGES (256*1024) // 1GB
+#define NB_PAGES (64*1024) // 256MB
#define NB_THREADS 16
#define MAP_PAGES_FLAGS (MAP_SHARED|MAP_ANONYMOUS|MAP_NORESERVE)
@@ -132,7 +132,6 @@
struct write_history_s {
struct write_history_s *previous_older_transaction;
- uint16_t transaction_version;
uint32_t nb_updates;
struct write_entry_s updates[];
};
@@ -143,14 +142,15 @@
at the cache line level --- we don't want the following few
variables to be accidentally in the same cache line. */
char pad0[CACHE_LINE_SIZE]; uint64_t volatile index_page_never_used;
+ char pad1[CACHE_LINE_SIZE]; uint16_t volatile next_transaction_version;
char pad2[CACHE_LINE_SIZE]; struct write_history_s *
volatile most_recent_committed_transaction;
char pad3[CACHE_LINE_SIZE];
};
struct alloc_for_size_s {
- char *next;
- char *end;
+ GCOBJECT char *next;
+ GCOBJECT char *end;
};
typedef GCOBJECT struct _thread_local2_s {
@@ -180,7 +180,7 @@
_Bool _stm_was_written(object_t *object)
{
- return (object->flags & GCFLAG_WRITE_BARRIER) == 0;
+ return (object->modif_version == _STM_TL1.transaction_version);
}
@@ -238,6 +238,8 @@
page = fetch_thread_local_page(page);
+ object->modif_version = _STM_TL1.transaction_version;
+
uint32_t write_log_index = page->write_log_index_cache;
struct write_history_s *log = _STM_TL2.writes_by_this_transaction;
@@ -251,6 +253,7 @@
log->updates[write_log_index].bitmask[1] = 0;
log->updates[write_log_index].bitmask[2] = 0;
log->updates[write_log_index].bitmask[3] = 0;
+ page->write_log_index_cache = write_log_index;
}
assert(byte_ofs16 < 256);
@@ -258,54 +261,38 @@
(1UL << (byte_ofs16 & 63));
}
-#if 0
-char *_stm_alloc_next_page(size_t i)
+GCOBJECT char *_stm_alloc_next_page(size_t i)
{
+ /* NB. 'newpage' points to the "object pages" area, but it is casted
+ to a 'GCOBJECT char *', which if dereferenced will produce a %gs
+ segment prefix and so will address the thread-local pages area. */
struct page_header_s *newpage = _stm_reserve_page();
- newpage->modif_head = 0xff;
- newpage->kind = i; /* object size in words */
- newpage->version = 0; /* a completely new page doesn't need a version */
- stm_local.alloc[i].next = ((char *)(newpage + 1)) + (i * 8);
- stm_local.alloc[i].end = ((char *)newpage) + 4096;
- assert(stm_local.alloc[i].next <= stm_local.alloc[i].end);
- return (char *)(newpage + 1);
+ newpage->obj_word_size = i;
+ newpage->thread_local_copy = 0;
+ _STM_TL2.alloc[i].next = ((GCOBJECT char *)(newpage + 1)) + (i * 8);
+ _STM_TL2.alloc[i].end = ((GCOBJECT char *)newpage) + 4096;
+ assert(_STM_TL2.alloc[i].next <= _STM_TL2.alloc[i].end);
+ return (GCOBJECT char *)(newpage + 1);
}
-struct object_s *stm_allocate(size_t size)
+object_t *stm_allocate(size_t size)
{
assert(size % 8 == 0);
size_t i = size / 8;
assert(2 <= i && i < LARGE_OBJECT_WORDS);//XXX
- struct alloc_for_size_s *alloc = &stm_local.alloc[i];
+ GCOBJECT struct alloc_for_size_s *alloc = &_STM_TL2.alloc[i];
- char *p = alloc->next;
+ GCOBJECT char *p = alloc->next;
alloc->next += size;
if (alloc->next > alloc->end)
p = _stm_alloc_next_page(i);
- struct object_s *result = (struct object_s *)p;
- result->modified = stm_transaction_version;
- /*result->modif_next is uninitialized*/
- result->flags = 0x42; /* for debugging */
+ object_t *result = (object_t *)p;
+ result->modif_version = _STM_TL1.transaction_version;
return result;
}
-
-unsigned char stm_get_read_marker_number(void)
-{
- return (unsigned char)(uintptr_t)stm_current_read_markers;
-}
-
-void stm_set_read_marker_number(uint8_t num)
-{
- char *stm_pages = ((char *)stm_shared_descriptor) + 4096;
- uintptr_t delta = ((uintptr_t)stm_pages) >> 4;
- struct _read_marker_s *crm = (struct _read_marker_s
*)stm_local.read_markers;
- stm_current_read_markers = crm - delta;
- assert(stm_get_read_marker_number() == 0);
- stm_current_read_markers += num;
-}
-
+#if 0
static void clear_all_read_markers(void)
{
/* set the largest possible read marker number, to find the last
@@ -353,6 +340,7 @@
abort();
}
stm_shared_descriptor.index_page_never_used = 0;
+ stm_shared_descriptor.next_transaction_version = 1;
}
void _stm_teardown(void)
@@ -364,7 +352,7 @@
static void set_gs_register(uint64_t value)
{
- int result = syscall(SYS_arch_prctl, ARCH_SET_GS, &value);
+ int result = syscall(SYS_arch_prctl, ARCH_SET_GS, value);
assert(result == 0);
}
@@ -404,7 +392,8 @@
uint64_t nb_rm_pages = (NB_PAGES + 15) >> 4;
if (mmap(local_RM_pages(gs_value), nb_rm_pages * 4096UL,
PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+ -1, 0) == MAP_FAILED) {
munmap(local_L0_pages(gs_value), 2 * 4096UL);
thnum++;
continue;
@@ -417,6 +406,8 @@
perror("remap_file_pages in stm_setup_thread");
abort();
}
+ /* XXX check if the following call doesn't force all pages to be
+ reserved or even zero-filled eagerly */
res = remap_file_pages(stm_object_pages + gs_value, NB_PAGES * 4096UL, 0,
0, MAP_PAGES_FLAGS);
if (res < 0) {
@@ -426,6 +417,8 @@
set_gs_register(gs_value);
_STM_TL2.gs_value = gs_value;
_STM_TL1.read_marker = 1;
+
+ fprintf(stderr, "new thread starting at %d (gs=0x%lx)\n", thnum, gs_value);
return thnum;
}
@@ -568,36 +561,28 @@
stm_local.base_page_mapping = new;
return conflict;
}
+#endif
void stm_start_transaction(void)
{
- struct shared_descriptor_s *d = stm_shared_descriptor;
- unsigned int v = __sync_fetch_and_add(&d->next_transaction_version, 2u);
+ struct shared_descriptor_s *d = &stm_shared_descriptor;
+ uint16_t v = __sync_fetch_and_add(&d->next_transaction_version, 1);
assert(v <= 0xffff);//XXX
- assert((v & 1) == 0); /* EVEN number */
- assert(v >= 2);
- stm_transaction_version = v;
+ _STM_TL1.transaction_version = v;
- struct write_history_s *cur = NULL;
- if (stm_local.writes_by_this_transaction != NULL) {
- cur = stm_local.writes_by_this_transaction;
- char *next, *page_limit = (char *)cur;
- page_limit += 4096 - (((uintptr_t)page_limit) & 4095);
- next = (char *)(cur + 1) + 8 * cur->nb_updates;
- if (page_limit - next < sizeof(struct write_history_s) + 8)
- cur = NULL;
- else
- cur = (struct write_history_s *)next;
- }
- if (cur == NULL) {
- cur = _reserve_page_write_history();
- }
- assert(cur != d->most_recent_committed_transaction);
- cur->previous_older_transaction = NULL;
- cur->transaction_version = stm_transaction_version;
- cur->nb_updates = 0;
- stm_local.writes_by_this_transaction = cur;
+ assert(_STM_TL2.writes_by_this_transaction == NULL);
+ _STM_TL2.nb_updates_max = 4; /* XXX for now */
+
+ struct write_history_s *log = (struct write_history_s *)
+ malloc(sizeof(struct write_history_s)
+ + _STM_TL2.nb_updates_max * sizeof(struct write_entry_s));
+ assert(log != NULL);
+
+ log->nb_updates = 0;
+ _STM_TL2.writes_by_this_transaction = log;
+
+#if 0
struct write_history_s *hist = d->most_recent_committed_transaction;
if (hist != stm_local.base_page_mapping) {
history_fast_forward(hist, 1);
@@ -614,43 +599,43 @@
usually it is read-only */
}
}
+#endif
}
_Bool stm_stop_transaction(void)
{
- struct shared_descriptor_s *d = stm_shared_descriptor;
- assert(stm_local.writes_by_this_transaction != NULL);
int conflict = 0;
+ struct shared_descriptor_s *d = &stm_shared_descriptor;
+ struct write_history_s *cur = _STM_TL2.writes_by_this_transaction;
+ assert(cur != NULL);
+ _STM_TL2.writes_by_this_transaction = NULL;
//fprintf(stderr, "stm_stop_transaction\n");
- struct write_history_s *cur_head = stm_local.writes_by_this_transaction;
- struct write_history_s *cur_tail = cur_head;
- while (cur_tail->previous_older_transaction != NULL) {
- cur_tail = cur_tail->previous_older_transaction;
- }
-
while (1) {
struct write_history_s *hist = d->most_recent_committed_transaction;
- if (hist != stm_local.base_page_mapping) {
- conflict = history_fast_forward(hist, 0);
+ if (hist != _STM_TL2.base_page_mapping) {
+ abort();
+ //XXX conflict = history_fast_forward(hist, 0);
if (conflict)
break;
else
continue; /* retry from the start of the loop */
}
- assert(cur_head == stm_local.writes_by_this_transaction);
- cur_tail->previous_older_transaction = hist;
+ cur->previous_older_transaction = hist;
if (__sync_bool_compare_and_swap(&d->most_recent_committed_transaction,
- hist, cur_head))
+ hist, cur))
break;
}
- if (stm_get_read_marker_number() < 0xff) {
- stm_current_read_markers++;
+ if (conflict) {
+ free(cur);
+ }
+
+ if (_STM_TL1.read_marker < 0xff) {
+ _STM_TL1.read_marker++;
}
else {
- clear_all_read_markers();
+ abort();//XXX clear_all_read_markers();
}
return !conflict;
}
-#endif
diff --git a/c5/core.h b/c5/core.h
--- a/c5/core.h
+++ b/c5/core.h
@@ -5,11 +5,9 @@
#define GCOBJECT __attribute__((address_space(256)))
-#define GCFLAG_WRITE_BARRIER 0x01
-
typedef GCOBJECT struct object_s {
/* Every objects starts with one such structure */
- uint8_t flags;
+ uint16_t modif_version;
} object_t;
struct _read_marker_s {
@@ -21,6 +19,7 @@
typedef GCOBJECT struct _thread_local1_s {
uint8_t read_marker;
+ uint16_t transaction_version;
} _thread_local1_t;
#define _STM_TL1 (((_thread_local1_t *)0)[-1])
@@ -46,7 +45,8 @@
static inline void stm_write(object_t *object)
{
- if (__builtin_expect((object->flags & GCFLAG_WRITE_BARRIER) != 0, 0))
+ uint16_t tversion = _STM_TL1.transaction_version;
+ if (__builtin_expect(object->modif_version != tversion, 0))
_stm_write_barrier_slowpath(object);
}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit