Author: Armin Rigo <[email protected]>
Branch: c8-hashtable
Changeset: r1713:397c4402e270
Date: 2015-03-10 20:01 +0100
http://bitbucket.org/pypy/stmgc/changeset/397c4402e270/
Log: Add the code from c7
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -284,6 +284,17 @@
static void _signal_handler(int sig, siginfo_t *siginfo, void *context);
static bool _stm_validate();
+static inline bool was_read_remote(char *base, object_t *obj)
+{
+ uint8_t other_transaction_read_version =
+ ((struct stm_segment_info_s *)REAL_ADDRESS(base, STM_PSEGMENT))
+ ->transaction_read_version;
+ uint8_t rm = ((struct stm_read_marker_s *)
+ (base + (((uintptr_t)obj) >> 4)))->rm;
+ assert(rm <= other_transaction_read_version);
+ return rm == other_transaction_read_version;
+}
+
static inline void _duck(void) {
/* put a call to _duck() between two instructions that set 0 into
a %gs-prefixed address and that may otherwise be replaced with
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -127,6 +127,56 @@
return o;
}
+static void _fill_preexisting_slice(long segnum, char *dest,
+ const char *src, uintptr_t size)
+{
+ uintptr_t np = dest - get_segment_base(segnum);
+ if (get_page_status_in(segnum, np / 4096) != PAGE_NO_ACCESS)
+ memcpy(dest, src, size);
+}
+
+object_t *stm_allocate_preexisting(ssize_t size_rounded_up,
+ const char *initial_data)
+{
+ stm_char *np = allocate_outside_nursery_large(size_rounded_up);
+ uintptr_t nobj = (uintptr_t)np;
+ dprintf(("allocate_preexisting: %p\n", (object_t *)nobj));
+
+ char *dest = stm_object_pages + nobj;
+ memcpy(dest, initial_data, size_rounded_up);
+ ((struct object_s *)dest)->stm_flags = GCFLAG_WRITE_BARRIER;
+
+ acquire_all_privatization_locks();
+
+ long j;
+ for (j = 1; j <= NB_SEGMENTS; j++) {
+ const char *src = initial_data;
+ char *dest = get_segment_base(j) + nobj;
+ char *end = dest + size_rounded_up;
+
+ while (((uintptr_t)dest) / 4096 != ((uintptr_t)end - 1) / 4096) {
+ uintptr_t count = 4096 - ((uintptr_t)dest) / 4096;
+ _fill_preexisting_slice(j, dest, src, count);
+ src += count;
+ dest += count;
+ }
+ _fill_preexisting_slice(j, dest, src, end - dest);
+
+#ifdef STM_TESTS
+ /* can't really enable this check outside tests, because there is
+ a change that the transaction_state changes in parallel */
+ if (get_priv_segment(j)->transaction_state != TS_NONE) {
+ assert(!was_read_remote(get_segment_base(j), (object_t *)nobj));
+ }
+#endif
+ }
+
+ release_all_privatization_locks();
+
+ write_fence(); /* make sure 'nobj' is fully initialized from
+ all threads here */
+ return (object_t *)nobj;
+}
/************************************************************/
diff --git a/c7/stm/hashtable.c b/c8/stm/hashtable.c
copy from c7/stm/hashtable.c
copy to c8/stm/hashtable.c
--- a/c7/stm/hashtable.c
+++ b/c8/stm/hashtable.c
@@ -110,7 +110,7 @@
/* can only be safely called during major GC, when all other threads
are suspended */
long i;
- for (i = 1; i <= NB_SEGMENTS; i++) {
+ for (i = 1; i < NB_SEGMENTS; i++) {
if (get_priv_segment(i)->transaction_state == TS_NONE)
continue;
if (was_read_remote(get_segment_base(i), obj))
diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -31,10 +31,7 @@
bool _stm_was_read(object_t *obj)
{
- uint8_t rm = ((struct stm_read_marker_s *)
- (STM_SEGMENT->segment_base + (((uintptr_t)obj) >> 4)))->rm;
- assert(rm <= STM_SEGMENT->transaction_read_version);
- return rm == STM_SEGMENT->transaction_read_version;
+ return was_read_remote(STM_SEGMENT->segment_base, obj);
}
bool _stm_was_written(object_t *obj)
diff --git a/c8/stmgc.c b/c8/stmgc.c
--- a/c8/stmgc.c
+++ b/c8/stmgc.c
@@ -39,3 +39,4 @@
#include "stm/prof.c"
#include "stm/rewind_setjmp.c"
#include "stm/finalizer.c"
+#include "stm/hashtable.c"
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -467,6 +467,37 @@
/* dummies for now: */
static inline void stm_flush_timing(stm_thread_local_t *tl, int verbose) {}
+
+/* Hashtables. Keys are 64-bit unsigned integers, values are
+ 'object_t *'. Note that the type 'stm_hashtable_t' is not an
+ object type at all; you need to allocate and free it explicitly.
+ If you want to embed the hashtable inside an 'object_t' you
+ probably need a light finalizer to do the freeing. */
+typedef struct stm_hashtable_s stm_hashtable_t;
+typedef TLPREFIX struct stm_hashtable_entry_s stm_hashtable_entry_t;
+
+stm_hashtable_t *stm_hashtable_create(void);
+void stm_hashtable_free(stm_hashtable_t *);
+stm_hashtable_entry_t *stm_hashtable_lookup(object_t *, stm_hashtable_t *,
+ uintptr_t key);
+object_t *stm_hashtable_read(object_t *, stm_hashtable_t *, uintptr_t key);
+void stm_hashtable_write(object_t *, stm_hashtable_t *, uintptr_t key,
+ object_t *nvalue, stm_thread_local_t *);
+void stm_hashtable_write_entry(object_t *hobj, stm_hashtable_entry_t *entry,
+ object_t *nvalue);
+long stm_hashtable_length_upper_bound(stm_hashtable_t *);
+long stm_hashtable_list(object_t *, stm_hashtable_t *,
+ stm_hashtable_entry_t **results);
+extern uint32_t stm_hashtable_entry_userdata;
+void stm_hashtable_tracefn(stm_hashtable_t *, void (object_t **));
+
+struct stm_hashtable_entry_s {
+ struct object_s header;
+ uint32_t userdata;
+ uintptr_t index;
+ object_t *object;
+};
+
/* ==================== END ==================== */
static void (*stmcb_expand_marker)(char *segment_base, uintptr_t odd_number,
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -197,6 +197,25 @@
void stm_enable_light_finalizer(object_t *);
void (*stmcb_finalizer)(object_t *);
+
+typedef struct stm_hashtable_s stm_hashtable_t;
+typedef ... stm_hashtable_entry_t;
+stm_hashtable_t *stm_hashtable_create(void);
+void stm_hashtable_free(stm_hashtable_t *);
+bool _check_hashtable_read(object_t *, stm_hashtable_t *, uintptr_t key);
+object_t *hashtable_read_result;
+bool _check_hashtable_write(object_t *, stm_hashtable_t *, uintptr_t key,
+ object_t *nvalue, stm_thread_local_t *tl);
+long stm_hashtable_length_upper_bound(stm_hashtable_t *);
+long stm_hashtable_list(object_t *, stm_hashtable_t *,
+ stm_hashtable_entry_t **results);
+uint32_t stm_hashtable_entry_userdata;
+void stm_hashtable_tracefn(stm_hashtable_t *, void (object_t **));
+
+void _set_hashtable(object_t *obj, stm_hashtable_t *h);
+stm_hashtable_t *_get_hashtable(object_t *obj);
+uintptr_t _get_entry_index(stm_hashtable_entry_t *entry);
+object_t *_get_entry_object(stm_hashtable_entry_t *entry);
""")
@@ -299,6 +318,19 @@
CHECKED(stm_validate());
}
+object_t *hashtable_read_result;
+
+bool _check_hashtable_read(object_t *hobj, stm_hashtable_t *h, uintptr_t key)
+{
+ CHECKED(hashtable_read_result = stm_hashtable_read(hobj, h, key));
+}
+
+bool _check_hashtable_write(object_t *hobj, stm_hashtable_t *h, uintptr_t key,
+ object_t *nvalue, stm_thread_local_t *tl)
+{
+ CHECKED(stm_hashtable_write(hobj, h, key, nvalue, tl));
+}
+
#undef CHECKED
@@ -326,6 +358,32 @@
return *WEAKREF_PTR(obj, size);
}
+void _set_hashtable(object_t *obj, stm_hashtable_t *h)
+{
+ stm_char *field_addr = ((stm_char*)obj);
+ field_addr += SIZEOF_MYOBJ; /* header */
+ *(stm_hashtable_t *TLPREFIX *)field_addr = h;
+}
+
+stm_hashtable_t *_get_hashtable(object_t *obj)
+{
+ stm_char *field_addr = ((stm_char*)obj);
+ field_addr += SIZEOF_MYOBJ; /* header */
+ return *(stm_hashtable_t *TLPREFIX *)field_addr;
+}
+
+uintptr_t _get_entry_index(stm_hashtable_entry_t *entry)
+{
+ stm_read((object_t *)entry);
+ return entry->index;
+}
+
+object_t *_get_entry_object(stm_hashtable_entry_t *entry)
+{
+ stm_read((object_t *)entry);
+ return entry->object;
+}
+
void _set_ptr(object_t *obj, int n, object_t *v)
{
long nrefs = (long)((myobj_t*)obj)->type_id - 421420;
@@ -351,11 +409,17 @@
}
-
ssize_t stmcb_size_rounded_up(struct object_s *obj)
{
struct myobj_s *myobj = (struct myobj_s*)obj;
+ assert(myobj->type_id != 0);
if (myobj->type_id < 421420) {
+ if (myobj->type_id == 421419) { /* hashtable */
+ return sizeof(struct myobj_s) + 1 * sizeof(void*);
+ }
+ if (myobj->type_id == 421418) { /* hashtable entry */
+ return sizeof(struct stm_hashtable_entry_s);
+ }
/* basic case: tid equals 42 plus the size of the object */
assert(myobj->type_id >= 42 + sizeof(struct myobj_s));
assert((myobj->type_id - 42) >= 16);
@@ -371,11 +435,21 @@
}
}
-
void stmcb_trace(struct object_s *obj, void visit(object_t **))
{
int i;
struct myobj_s *myobj = (struct myobj_s*)obj;
+ if (myobj->type_id == 421419) {
+ /* hashtable */
+ stm_hashtable_t *h = *((stm_hashtable_t **)(myobj + 1));
+ stm_hashtable_tracefn(h, visit);
+ return;
+ }
+ if (myobj->type_id == 421418) {
+ /* hashtable entry */
+ object_t **ref = &((struct stm_hashtable_entry_s *)myobj)->object;
+ visit(ref);
+ }
if (myobj->type_id < 421420) {
/* basic case: no references */
return;
@@ -396,6 +470,7 @@
{
int i;
struct myobj_s *myobj = (struct myobj_s*)obj;
+ assert(myobj->type_id != 0);
assert(myobj->type_id != 421419);
assert(myobj->type_id != 421418);
if (myobj->type_id < 421420) {
@@ -413,6 +488,9 @@
uintptr_t offset_itemsize[2])
{
struct myobj_s *myobj = (struct myobj_s*)obj;
+ assert(myobj->type_id != 0);
+ assert(myobj->type_id != 421419);
+ assert(myobj->type_id != 421418);
if (myobj->type_id < 421420) {
offset_itemsize[0] = SIZEOF_MYOBJ;
offset_itemsize[1] = 1;
@@ -467,6 +545,7 @@
CARD_CLEAR = 0
CARD_MARKED = lib._STM_CARD_MARKED
CARD_MARKED_OLD = lib._stm_get_transaction_read_version
+lib.stm_hashtable_entry_userdata = 421418
class Conflict(Exception):
@@ -529,6 +608,18 @@
lib._set_type_id(o, tid)
return o
+def stm_allocate_hashtable():
+ o = lib.stm_allocate(16)
+ tid = 421419
+ lib._set_type_id(o, tid)
+ h = lib.stm_hashtable_create()
+ lib._set_hashtable(o, h)
+ return o
+
+def get_hashtable(o):
+ assert lib._get_type_id(o) == 421419
+ return lib._get_hashtable(o)
+
def stm_get_weakref(o):
return lib._get_weakref(o)
diff --git a/c7/test/test_hashtable.py b/c8/test/test_hashtable.py
copy from c7/test/test_hashtable.py
copy to c8/test/test_hashtable.py
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit