Commits

Armin Rigo  committed 912a831

progress

  • Participants
  • Parent commits 638f54c

Comments (0)

Files changed (3)

File hack/pypy-hack/rewind_setjmp/rewind_setjmp.c

 #include <assert.h>
 #include <alloca.h>
 
-__thread struct _rewind_jmp_s _rewind_jmp;
-
 
 struct _rewind_jmp_moved_s {
     struct _rewind_jmp_moved_s *next;
 #endif
 
 
+static void copy_stack(rewind_jmp_thread *rjthread, char *base)
+{
+    char *stop = (char *)rjthread->head;
+    assert(stop > base);
+    struct _rewind_jmp_moved_s *next = (struct _rewind_jmp_moved_s *)
+        rj_malloc(RJM_HEADER + (stop - base));
+    assert(next != NULL);    /* XXX out of memory */
+    next->next = rjthread->moved_off;
+    next->size = stop - base;
+    memcpy(((char *)next) + RJM_HEADER, base, stop - base);
+
+    rjthread->moved_off_base = rjthread->head;
+    rjthread->moved_off = next;
+}
+
 __attribute__((noinline))
-void _rewind_jmp_longjmp(char *stack_free)
+int rewind_jmp_setjmp(rewind_jmp_thread *rjthread)
 {
-    assert(_rewind_jmp.moved_off_base != NULL);
+    if (rjthread->moved_off) {
+        _rewind_jmp_free_stack_slices(rjthread);
+    }
+    int result;
+    if (__builtin_setjmp(rjthread->jmpbuf) == 0) {
+        rjthread->initial_head = rjthread->head;
+        result = 0;
+    }
+    else {
+        rjthread->head = rjthread->initial_head;
+        result = 1;
+    }
+    long stack_base;
+    copy_stack(rjthread, (char *)&stack_base);
+    return result;
+}
 
-    while (_rewind_jmp.moved_off) {
-        struct _rewind_jmp_moved_s *p = _rewind_jmp.moved_off;
-        char *target = (char *)_rewind_jmp.moved_off_base;
+__attribute__((noinline))
+static void do_longjmp(rewind_jmp_thread *rjthread, char *stack_free)
+{
+    assert(rjthread->moved_off_base != NULL);
+
+    while (rjthread->moved_off) {
+        struct _rewind_jmp_moved_s *p = rjthread->moved_off;
+        char *target = (char *)rjthread->moved_off_base;
         target -= p->size;
         if (target < stack_free) {
             /* need more stack space! */
-            _rewind_jmp_longjmp(alloca(stack_free - target));
+            do_longjmp(rjthread, alloca(stack_free - target));
         }
         memcpy(target, ((char *)p) + RJM_HEADER, p->size);
-        _rewind_jmp.moved_off_base = (rewind_jmp_buf *)target;
-        _rewind_jmp.moved_off = p->next;
+        rjthread->moved_off_base = (rewind_jmp_buf *)target;
+        rjthread->moved_off = p->next;
         rj_free(p);
     }
-    _rewind_jmp.head = _rewind_jmp.moved_off_base;
-    __builtin_longjmp(_rewind_jmp.jmpbuf, 1);
+    __builtin_longjmp(rjthread->jmpbuf, 1);
+}
+
+void rewind_jmp_longjmp(rewind_jmp_thread *rjthread)
+{
+    char _rewind_jmp_marker;
+    do_longjmp(rjthread, &_rewind_jmp_marker);
 }
 
 __attribute__((noinline))
-void _rewind_jmp_copy_stack_slice(void)
+void _rewind_jmp_copy_stack_slice(rewind_jmp_thread *rjthread)
 {
-    if (_rewind_jmp.head == NULL) {
-        _rewind_jmp_free_stack_slices();
+    if (rjthread->head == NULL) {
+        _rewind_jmp_free_stack_slices(rjthread);
         return;
     }
-    char *base = (char *)_rewind_jmp.moved_off_base;
-    assert(_rewind_jmp.moved_off_base->prev == _rewind_jmp.head);
-    _rewind_jmp.moved_off_base = _rewind_jmp.head;
-    char *stop = (char *)_rewind_jmp.moved_off_base;
-    assert(stop > base);
-
-    struct _rewind_jmp_moved_s *next = (struct _rewind_jmp_moved_s *)
-        rj_malloc(RJM_HEADER + (stop - base));
-    assert(next != NULL);    /* XXX out of memory */
-    next->next = _rewind_jmp.moved_off;
-    next->size = stop - base;
-    _rewind_jmp.moved_off = next;
-    memcpy(((char *)next) + RJM_HEADER, base, stop - base);
+    assert(rjthread->moved_off_base->prev == rjthread->head);
+    copy_stack(rjthread, (char *)rjthread->moved_off_base);
 }
 
-void _rewind_jmp_free_stack_slices(void)
+void _rewind_jmp_free_stack_slices(rewind_jmp_thread *rjthread)
 {
-    struct _rewind_jmp_moved_s *p = _rewind_jmp.moved_off;
+    struct _rewind_jmp_moved_s *p = rjthread->moved_off;
     struct _rewind_jmp_moved_s *pnext;
     while (p) {
         pnext = p->next;
         rj_free(p);
         p = pnext;
     }
-    _rewind_jmp.moved_off = NULL;
-    _rewind_jmp.moved_off_base = NULL;
+    rjthread->moved_off = NULL;
+    rjthread->moved_off_base = NULL;
 }

File hack/pypy-hack/rewind_setjmp/rewind_setjmp.h

     struct _rewind_jmp_buf *prev;
 } rewind_jmp_buf;
 
-struct _rewind_jmp_s {
+typedef struct _rewind_jmp_s {
     rewind_jmp_buf *head;
+    rewind_jmp_buf *initial_head;
     rewind_jmp_buf *moved_off_base;
     struct _rewind_jmp_moved_s *moved_off;
     void *jmpbuf[5];
-};
+} rewind_jmp_thread;
 
-extern __thread struct _rewind_jmp_s _rewind_jmp;
 
-
-#define rewind_jmp_enterframe(rjbuf)   do {     \
-    rjbuf.prev = _rewind_jmp.head;              \
-    _rewind_jmp.head = &rjbuf;                  \
+#define rewind_jmp_enterframe(rjthread, rjbuf)   do {   \
+    (rjbuf)->prev = (rjthread)->head;                   \
+    (rjthread)->head = (rjbuf);                         \
 } while (0)
 
-#define rewind_jmp_leaveframe(rjbuf)   do {     \
-    _rewind_jmp.head = rjbuf.prev;              \
-    if (&rjbuf == _rewind_jmp.moved_off_base)   \
-        _rewind_jmp_copy_stack_slice();         \
+#define rewind_jmp_leaveframe(rjthread, rjbuf)   do {   \
+    (rjthread)->head = (rjbuf)->prev;                   \
+    if ((rjbuf) == (rjthread)->moved_off_base)          \
+        _rewind_jmp_copy_stack_slice(rjthread);         \
 } while (0)
 
-#define rewind_jmp_setjmp()   do {                              \
-    if (_rewind_jmp.moved_off) _rewind_jmp_free_stack_slices(); \
-    while (__builtin_setjmp(_rewind_jmp.jmpbuf) != 0) { }       \
-    _rewind_jmp.moved_off_base = _rewind_jmp.head;              \
+int rewind_jmp_setjmp(rewind_jmp_thread *rjthread);
+void rewind_jmp_longjmp(rewind_jmp_thread *rjthread);
+
+#define rewind_jmp_forget(rjthread)  do {                               \
+    if ((rjthread)->moved_off) _rewind_jmp_free_stack_slices(rjthread); \
+    (rjthread)->moved_off_base = 0;                                     \
 } while (0)
 
-#define rewind_jmp_longjmp()   do {                     \
-    char _rewind_jmp_marker;                            \
-    _rewind_jmp_longjmp(&_rewind_jmp_marker);           \
-} while (0)
-
-#define rewind_jmp_forget()  do {                               \
-    if (_rewind_jmp.moved_off) _rewind_jmp_free_stack_slices(); \
-    _rewind_jmp.moved_off_base = 0;                             \
-} while (0)
-
-void _rewind_jmp_longjmp(char *);
-void _rewind_jmp_copy_stack_slice(void);
-void _rewind_jmp_free_stack_slices(void);
+void _rewind_jmp_copy_stack_slice(rewind_jmp_thread *);
+void _rewind_jmp_free_stack_slices(rewind_jmp_thread *);
 
 #endif

File hack/pypy-hack/rewind_setjmp/test_rewind.c

 #include <assert.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "rewind_setjmp.h"
 
 
+rewind_jmp_thread gthread;
 int gevents[1000];
 int num_gevents = 0;
 
 void gevent(int num)
 {
+    assert(num_gevents <= sizeof(gevents) / sizeof(int));
     gevents[num_gevents++] = num;
 }
 
 {
     gevent(1);
     if (x < 10) {
-        rewind_jmp_longjmp();
+        rewind_jmp_longjmp(&gthread);
     }
 }
 
+static int test1_x;
+
 void test1(void)
 {
     rewind_jmp_buf buf;
-    rewind_jmp_enterframe(buf);
+    rewind_jmp_enterframe(&gthread, &buf);
 
-    volatile int x = 0;
-    rewind_jmp_setjmp();
+    test1_x = 0;
+    rewind_jmp_setjmp(&gthread);
 
-    x++;
-    f1(x);
+    test1_x++;
+    f1(test1_x);
 
-    assert(x == 10);
+    assert(test1_x == 10);
     int expected[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
     CHECK(expected);
 
-    rewind_jmp_leaveframe(buf);
+    rewind_jmp_leaveframe(&gthread, &buf);
 }
 
 /************************************************************/
 
+static int test2_x;
+
 __attribute__((noinline))
 int f2(void)
 {
     rewind_jmp_buf buf;
-    rewind_jmp_enterframe(buf);
-    volatile int x = 0;
-    rewind_jmp_setjmp();
-    rewind_jmp_leaveframe(buf);
-    return ++x;
+    rewind_jmp_enterframe(&gthread, &buf);
+    test2_x = 0;
+    rewind_jmp_setjmp(&gthread);
+    rewind_jmp_leaveframe(&gthread, &buf);
+    return ++test2_x;
 }
 
 void test2(void)
 {
     rewind_jmp_buf buf;
-    rewind_jmp_enterframe(buf);
+    rewind_jmp_enterframe(&gthread, &buf);
     int x = f2();
     gevent(x);
     if (x < 10)
-        rewind_jmp_longjmp();
-    rewind_jmp_leaveframe(buf);
+        rewind_jmp_longjmp(&gthread);
+    rewind_jmp_leaveframe(&gthread, &buf);
     int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     CHECK(expected);
 }
 void test3(void)
 {
     rewind_jmp_buf buf;
-    rewind_jmp_enterframe(buf);
+    rewind_jmp_enterframe(&gthread, &buf);
     int x = f3(50);
     gevent(x);
     if (x < 10)
-        rewind_jmp_longjmp();
-    rewind_jmp_leaveframe(buf);
+        rewind_jmp_longjmp(&gthread);
+    rewind_jmp_leaveframe(&gthread, &buf);
     int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     CHECK(expected);
 }
 int f4(int rec)
 {
     rewind_jmp_buf buf;
-    rewind_jmp_enterframe(buf);
+    rewind_jmp_enterframe(&gthread, &buf);
     int res;
     if (rec > 0)
         res = f4(rec - 1);
     else
         res = f2();
-    rewind_jmp_leaveframe(buf);
+    rewind_jmp_leaveframe(&gthread, &buf);
     return res;
 }
 
 void test4(void)
 {
     rewind_jmp_buf buf;
-    rewind_jmp_enterframe(buf);
-    int x = f4(50);
+    rewind_jmp_enterframe(&gthread, &buf);
+    int x = f4(5);
     gevent(x);
     if (x < 10)
-        rewind_jmp_longjmp();
-    rewind_jmp_leaveframe(buf);
+        rewind_jmp_longjmp(&gthread);
+    rewind_jmp_leaveframe(&gthread, &buf);
     int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     CHECK(expected);
 }
 void *rj_malloc(size_t size)
 {
     rj_malloc_count++;
-    return malloc(size);
+    void *ptr = malloc(size);
+    fprintf(stderr, "malloc(%ld) -> %p\n", (long)size, ptr);
+    return ptr;
 }
 
 void rj_free(void *ptr)
 {
     if (ptr)
         rj_malloc_count--;
+    fprintf(stderr, "free(%p)\n", ptr);
     free(ptr);
 }