Author: Armin Rigo <ar...@tunes.org> Branch: continulet-jit Changeset: r53022:e8a39aa24c9b Date: 2012-02-29 17:53 +0100 http://bitbucket.org/pypy/pypy/changeset/e8a39aa24c9b/
Log: Random progress. diff --git a/pypy/translator/c/src/stacklet/stacklet.c b/pypy/translator/c/src/stacklet/stacklet.c --- a/pypy/translator/c/src/stacklet/stacklet.c +++ b/pypy/translator/c/src/stacklet/stacklet.c @@ -33,9 +33,13 @@ /************************************************************/ +struct cap_loc_s { + char **cl_original_pointer; + struct stacklet_s **cl_contained_in_stacklet; + struct cap_loc_s *cl_next; +} + struct stacklet_s { - stacklet_id id; /* first field */ - /* The portion of the real stack claimed by this paused tealet. */ char *stack_start; /* the "near" end of the stack */ char *stack_stop; /* the "far" end of the stack */ @@ -54,6 +58,9 @@ * main stack. */ struct stacklet_s *stack_prev; + + /* the captured stack locations */ + struct cap_loc_s *stack_cap_locs; }; void *(*_stacklet_switchstack)(void*(*)(void*, void*), @@ -61,20 +68,18 @@ void (*_stacklet_initialstub)(struct stacklet_thread_s *, stacklet_run_fn, void *) = NULL; -struct stacklet_id_s { - stacklet_handle stacklet; -}; - struct stacklet_thread_s { - stacklet_id g_current_id; /* first field */ struct stacklet_s *g_stack_chain_head; /* NULL <=> running main */ char *g_current_stack_stop; char *g_current_stack_marker; struct stacklet_s *g_source; struct stacklet_s *g_target; - struct stacklet_id_s g_main_id; + struct stacklet_thread_s *g_prev_thread, *g_next_thread; }; +/* circular doubly-linked list */ +static struct stacklet_thread_s *g_all_threads = NULL; + /***************************************************************/ static void g_save(struct stacklet_s* g, char* stop @@ -136,8 +141,6 @@ return -1; stacklet = thrd->g_source; - stacklet->id = thrd->g_current_id; - stacklet->id->stacklet = stacklet; stacklet->stack_start = old_stack_pointer; stacklet->stack_stop = thrd->g_current_stack_stop; stacklet->stack_saved = 0; @@ -237,8 +240,6 @@ memcpy(g->stack_start - stack_saved, g+1, stack_saved); #endif thrd->g_current_stack_stop = g->stack_stop; - thrd->g_current_id = g->id; - thrd->g_current_id->stacklet = NULL; free(g); return EMPTY_STACKLET_HANDLE; } @@ -247,12 +248,12 @@ stacklet_run_fn run, void *run_arg) { struct stacklet_s *result; - stacklet_id sid1 = thrd->g_current_id; + /*stacklet_id sid1 = thrd->g_current_id; stacklet_id sid = malloc(sizeof(struct stacklet_id_s)); if (sid == NULL) { thrd->g_source = NULL; return; - } + }*/ /* The following call returns twice! */ result = (struct stacklet_s *) _stacklet_switchstack(g_initial_save_state, @@ -261,18 +262,18 @@ if (result == NULL) { /* First time it returns. */ if (thrd->g_source == NULL) { /* out of memory */ - free(sid); + /*free(sid);*/ return; } /* Only g_initial_save_state() has run and has created 'g_source'. Call run(). */ - sid->stacklet = NULL; - thrd->g_current_id = sid; + /*sid->stacklet = NULL; + thrd->g_current_id = sid;*/ thrd->g_current_stack_stop = thrd->g_current_stack_marker; result = run(thrd->g_source, run_arg); /* Then switch to 'result'. */ - free(sid); + /*free(sid);*/ thrd->g_target = result; _stacklet_switchstack(g_destroy_state, g_restore_state, thrd); @@ -280,7 +281,7 @@ abort(); } /* The second time it returns. */ - assert(thrd->g_current_id == sid1); + /*assert(thrd->g_current_id == sid1);*/ } /************************************************************/ @@ -299,13 +300,36 @@ thrd = malloc(sizeof(struct stacklet_thread_s)); if (thrd != NULL) { memset(thrd, 0, sizeof(struct stacklet_thread_s)); - thrd->g_current_id = &thrd->g_main_id; + if (g_all_threads == NULL) { + g_all_threads = thrd; + thrd->g_prev_thread = thrd; + thrd->g_next_thread = thrd; + } + else { + struct stacklet_thread_s *next = g_all_threads->g_next_thread; + thrd->g_prev_thread = g_all_threads; + thrd->g_next_thread = next; + g_all_threads->g_next_thread = thrd; + next->g_prev_thread = thrd; + } } return thrd; } void stacklet_deletethread(stacklet_thread_handle thrd) { + /* remove 'thrd' from the circular doubly-linked list */ + stacklet_thread_handle prev = thrd->g_prev_thread; + stacklet_thread_handle next = thrd->g_next_thread; + assert(next->g_prev_thread == thrd); + assert(prev->g_next_thread == thrd); + next->g_prev_thread = prev; + prev->g_next_thread = next; + assert(g_all_threads != NULL); + if (g_all_threads == thrd) { + g_all_threads = (next == thrd) ? NULL : next; + } + /* free it */ free(thrd); } @@ -343,9 +367,9 @@ *pp = target->stack_prev; break; } - assert(target->id->stacklet == target); + /*assert(target->id->stacklet == target); if (target->id != &thrd->g_main_id) - free(target->id); + free(target->id);*/ free(target); } @@ -371,3 +395,64 @@ } return ptr; } + +long _stacklet_capture_stack_pointer(stacklet_thread_handle thrd, + char **stackptr) +{ + if (thrd->g_stack_chain_head == NULL) { + /* running in 'main' */ + return (long)stackptr; + } + else { + fprintf(stderr, "1!\n"); + abort(); + } +} + +char **_stacklet_get_captured_pointer(long captured) +{ + if ((captured & 1) == 0) { + return (char**)captured; + } + else { + fprintf(stderr, "2!\n"); + abort(); + } +} + +stacklet_handle _stacklet_get_captured_context(long captured) +{ + if ((captured & 1) == 0) { + /* it is one of the 'main' stacklets. If it was moved away, + we need to figure out which one it was. */ + char *p = (char *)captured; + struct stacklet_thread_s *thrd = g_all_threads; + if (thrd == NULL) + return NULL; /* no stacklet_thread at all */ + + while (1) { + struct stacklet_s *stacklet = thrd->g_stack_chain_head; + if (stacklet != NULL) { + /* not running 'main'. Find the main stacklet */ + while (stacklet->stack_prev) + stacklet = stacklet->stack_prev; + + /* is 'captured' among the moved-away data? */ + if (stacklet->stack_start <= p && p < stacklet->stack_stop) { + /* yes. to optimize the next calls make g_all_threads + point directly to thrd. */ + g_all_threads = thrd; + return stacklet; + } + } + thrd = thrd->g_next_thread; + if (thrd == g_all_threads) + break; + } + return NULL; + } + else { + fprintf(stderr, "3!\n"); + abort(); + } +} diff --git a/pypy/translator/c/src/stacklet/stacklet.h b/pypy/translator/c/src/stacklet/stacklet.h --- a/pypy/translator/c/src/stacklet/stacklet.h +++ b/pypy/translator/c/src/stacklet/stacklet.h @@ -72,8 +72,14 @@ * the main stacklet. This guarantees that it is possible to use * '_stacklet_get_...()' on a regular address taken before starting * to use stacklets. + * + * XXX assumes a single stacklet_thread_handle per thread + * + * XXX _stacklet_capture_stack_pointer() invalidates all 'long' values + * previously returned for the same stacklet that were for addresses + * later in the stack (i.e. lower). */ -long _stacklet_capture_stack_pointer(char **stackptr); +long _stacklet_capture_stack_pointer(stacklet_thread_handle, char **stackptr); char **_stacklet_get_captured_pointer(long captured); stacklet_handle _stacklet_get_captured_context(long captured); diff --git a/pypy/translator/c/src/stacklet/tests.c b/pypy/translator/c/src/stacklet/tests.c --- a/pypy/translator/c/src/stacklet/tests.c +++ b/pypy/translator/c/src/stacklet/tests.c @@ -628,8 +628,9 @@ /************************************************************/ struct test_captr_s { - long c, c1, c2; + long c, c0, c1, c2; char **fooref; + char **fooref0; char **fooref1; char **fooref2; stacklet_handle hmain; @@ -637,7 +638,7 @@ stacklet_handle h2; } tid; -void cap_check_all(int depth); +int cap_check_all(int depth); stacklet_handle stacklet_captr_callback_1(stacklet_handle h, void *arg) { @@ -647,11 +648,11 @@ status = 1; assert(_stacklet_get_captured_pointer(tid.c) == tid.fooref); - assert(_stacklet_get_captured_context(tid.c) == tid.hmain); + assert(_stacklet_get_captured_context(tid.c) == NULL); assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42); char *ref1 = (char*)1111; - tid.c1 = _stacklet_capture_stack_pointer(&ref1); + tid.c1 = _stacklet_capture_stack_pointer(thrd, &ref1); tid.fooref1 = &ref1; assert(_stacklet_get_captured_pointer(tid.c1) == &ref1); assert(_stacklet_get_captured_context(tid.c1) == NULL); @@ -675,13 +676,11 @@ status = 2; char *ref2 = (char*)2222; - tid.c2 = _stacklet_capture_stack_pointer(&ref2); + tid.c2 = _stacklet_capture_stack_pointer(thrd, &ref2); tid.fooref2 = &ref2; assert(_stacklet_get_captured_pointer(tid.c2) == &ref2); assert(_stacklet_get_captured_context(tid.c2) == NULL); - cap_check_all(20); - h = stacklet_switch(thrd, h); tid.hmain = h; tid.h2 = NULL; @@ -694,11 +693,17 @@ return stacklet_switch(thrd, h); } -void cap_check_all(int depth) +int cap_check_all(int depth) { assert(_stacklet_get_captured_pointer(tid.c) == tid.fooref); + /* we always get NULL because it's before the portion of the stack + that is copied away and restored: */ + assert(_stacklet_get_captured_context(tid.c) == NULL); + assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42); + + assert(_stacklet_get_captured_pointer(tid.c0) == tid.fooref0); assert(_stacklet_get_captured_context(tid.c) == tid.hmain); - assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42); + assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)6363); assert(_stacklet_get_captured_pointer(tid.c1) == tid.fooref1); assert(_stacklet_get_captured_context(tid.c1) == tid.h1); @@ -709,39 +714,26 @@ assert(*_stacklet_translate_pointer(tid.h2, tid.fooref2) == (char*)2222); if (depth > 0) - cap_check_all(depth - 1); - - assert(_stacklet_get_captured_pointer(tid.c) == tid.fooref); - assert(_stacklet_get_captured_context(tid.c) == tid.hmain); - assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42); - - assert(_stacklet_get_captured_pointer(tid.c1) == tid.fooref1); - assert(_stacklet_get_captured_context(tid.c1) == tid.h1); - assert(*_stacklet_translate_pointer(tid.h1, tid.fooref1) == (char*)1111); - - assert(_stacklet_get_captured_pointer(tid.c2) == tid.fooref2); - assert(_stacklet_get_captured_context(tid.c2) == tid.h2); - assert(*_stacklet_translate_pointer(tid.h2, tid.fooref2) == (char*)2222); + return cap_check_all(depth - 1) * depth; + return 1; } -void test_stacklet_capture(void) +int cap_with_extra_stack(int depth) { - char *foo = (char*)-42; - tid.c = _stacklet_capture_stack_pointer(&foo); - tid.fooref = &foo; - assert(tid.c == (long)tid.fooref); - assert(_stacklet_get_captured_pointer(tid.c) == &foo); - assert(_stacklet_get_captured_context(tid.c) == NULL); + stacklet_handle h1, h2; + char *foo0 = (char*)6363; - status = 0; - stacklet_handle h1 = stacklet_new(thrd, stacklet_captr_callback_1, NULL); - stacklet_handle h2 = stacklet_new(thrd, stacklet_captr_callback_2, NULL); - tid.hmain = NULL; - tid.h1 = h1; - tid.h2 = h2; + if (depth > 0) + return cap_with_extra_stack(depth - 1) * depth; + + tid.c0 = _stacklet_capture_stack_pointer(thrd, &foo0); + tid.fooref0 = &foo0; + assert(tid.c0 == (long)tid.fooref0); + assert(_stacklet_get_captured_pointer(tid.c0) == &foo0); + assert(_stacklet_get_captured_context(tid.c0) == NULL); cap_check_all(20); - assert(_stacklet_capture_stack_pointer(tid.fooref) == tid.c); + assert(_stacklet_capture_stack_pointer(thrd, tid.fooref) == tid.c); assert(status == 2); status = 3; @@ -758,11 +750,31 @@ tid.h2 = h2; cap_check_all(20); + return 1; +} + +void test_stacklet_capture(void) +{ + char *foo = (char*)-42; + tid.c = _stacklet_capture_stack_pointer(thrd, &foo); + tid.fooref = &foo; + assert(tid.c == (long)tid.fooref); + assert(_stacklet_get_captured_pointer(tid.c) == &foo); + assert(_stacklet_get_captured_context(tid.c) == NULL); + + status = 0; + stacklet_handle h1 = stacklet_new(thrd, stacklet_captr_callback_1, NULL); + stacklet_handle h2 = stacklet_new(thrd, stacklet_captr_callback_2, NULL); + tid.hmain = NULL; + tid.h1 = h1; + tid.h2 = h2; + + cap_with_extra_stack(20); assert(status == 6); - h1 = stacklet_switch(thrd, h1); + h1 = stacklet_switch(thrd, tid.h1); assert(h1 == EMPTY_STACKLET_HANDLE); - h2 = stacklet_switch(thrd, h2); + h2 = stacklet_switch(thrd, tid.h2); assert(h2 == EMPTY_STACKLET_HANDLE); } _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit