Author: Remi Meier <[email protected]>
Branch: 
Changeset: r195:bbf01c89fe52
Date: 2013-06-19 14:32 +0200
http://bitbucket.org/pypy/stmgc/changeset/bbf01c89fe52/

Log:    first random-test version in C. may have some bugs..

diff --git a/c4/demo_random.c b/c4/demo_random.c
new file mode 100644
--- /dev/null
+++ b/c4/demo_random.c
@@ -0,0 +1,316 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+
+#include "stmgc.h"
+#include "fprintcolor.h"
+
+
+#define NUMTHREADS 4
+#define STEPS 100000
+#define NUMROOTS 10
+#define PREBUILT 3
+#define MAXROOTS 1000
+#define SHARED_ROOTS 5
+
+
+// SUPPORT
+#define GCTID_STRUCT_ROOT     123
+
+struct root {
+    struct stm_object_s hdr;
+    long value;
+    struct root *next;
+};
+typedef struct root * rootptr;
+
+size_t stmcb_size(gcptr ob)
+{
+    assert(stm_get_tid(ob) == GCTID_STRUCT_ROOT);
+    return sizeof(struct root);
+}
+void stmcb_trace(gcptr ob, void visit(gcptr *))
+{
+    rootptr n;
+    assert(stm_get_tid(ob) == GCTID_STRUCT_ROOT);
+    n = (rootptr)ob;
+    visit((gcptr *)&n->next);
+}
+
+// global and per-thread-data
+time_t default_seed;
+gcptr shared_roots[SHARED_ROOTS];
+__thread unsigned int thread_seed = 0;
+__thread gcptr roots[MAXROOTS];
+__thread gcptr roots_outside_perform[MAXROOTS];
+__thread gcptr current_root = 0;
+__thread int num_roots = 0;
+__thread int num_roots_outside_perform = 0;
+__thread int steps_left;
+__thread int interruptible = 0;
+
+
+// helper functions
+int get_rand(int max)
+{
+    return (int)(rand_r(&thread_seed) % (unsigned int)max);
+}
+
+void copy_roots(gcptr *from, gcptr *to)
+{
+    int i;
+    for (i = 0; i < num_roots; i++)
+        *(to++) = *(from++);
+}
+
+gcptr allocate_pseudoprebuilt(size_t size, int tid)
+{
+    gcptr x = calloc(1, size);
+    x->h_tid = PREBUILT_FLAGS | tid;
+    x->h_revision = PREBUILT_REVISION;
+    return x;
+}
+
+void push_roots()
+{
+    int i;
+    for (i = 0; i < num_roots; i++)
+        stm_push_root(roots[i]);
+}
+
+void pop_roots()
+{
+    int i;
+    for (i = num_roots - 1; i >= 0; i--)
+        roots[i] = stm_pop_root();
+}
+
+void del_root(int idx)
+{
+    int i;
+    for (i = idx; i < num_roots - 1; i++)
+        roots[i] = roots[i + 1];
+}
+
+gcptr allocate_root(size_t size, int tid)
+{
+    gcptr r;
+    push_roots();
+    r = stm_allocate(size, tid);
+    pop_roots();
+    return r;
+}
+
+
+
+// THREAD TESTER
+int interruptible_callback(gcptr arg1, int retry_counter);
+int run_me();
+void transaction_break();
+
+void setup_thread()
+{
+    int i;
+    thread_seed = default_seed;
+    steps_left = STEPS;
+    interruptible = 0;
+    
+    num_roots = PREBUILT + NUMROOTS;
+    for (i = 0; i < PREBUILT; i++) {
+        roots[i] = allocate_pseudoprebuilt(sizeof(struct root), 
+                                           GCTID_STRUCT_ROOT);
+    }
+    for (i = PREBUILT; i < PREBUILT + NUMROOTS; i++) {
+        roots[i] = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT);
+    }
+
+}
+
+gcptr do_step(gcptr p)
+{
+    fprintf(stdout, "#");
+    
+    rootptr w_r, w_sr;
+    gcptr _r, _sr;
+    int num, k;
+
+    num = get_rand(num_roots);
+    _r = roots[num];
+
+    num = get_rand(SHARED_ROOTS);
+    _sr = shared_roots[num];
+
+    k = get_rand(14);
+
+    if (!p) // some parts expect it to be != 0
+        p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT);
+
+    switch (k) {
+    case 0: // remove a root
+        if (num > 0)
+            del_root(num);
+        break;
+    case 1: // set 'p' to point to a root
+        if (_r)
+            p = _r;
+        break;
+    case 2: // add 'p' to roots
+        if (num_roots < MAXROOTS)
+            roots[num_roots++] = p;
+        break;
+    case 3: // allocate fresh 'p'
+        p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT);
+        break;
+    case 4: // set 'p' as *next in one of the roots
+        w_r = (rootptr)stm_write_barrier(_r);
+        // XXX: do I have to read_barrier(p)?
+        w_r->next = (struct root*)p;
+        break;
+    case 5:  // read and validate 'p'
+        stm_read_barrier(p);
+        break;
+    case 6: // transaction break
+        if (interruptible)
+            return -1; // break current
+        transaction_break();
+        p = NULL;
+        break;
+    case 7: // only do a stm_write_barrier
+        p = stm_write_barrier(p);
+        break;
+    case 8:
+        p = (gcptr)(((rootptr)stm_read_barrier(p))->next);
+        break;
+    case 9: // XXX: rare events
+        break;
+    case 10: // only do a stm_read_barrier
+        p = stm_read_barrier(p);
+        break;
+    case 11:
+        stm_read_barrier(_sr);
+        break;
+    case 12:
+        stm_write_barrier(_sr);
+        break;
+    case 13:
+        w_sr = stm_write_barrier(_sr);
+        w_sr->next = shared_roots[get_rand(SHARED_ROOTS)];
+    default:
+        break;
+    }
+    return p;
+}
+
+
+void transaction_break()
+{
+    push_roots();
+    interruptible = 1;
+    
+    copy_roots(roots, roots_outside_perform);
+    num_roots_outside_perform = num_roots;
+    
+    stm_perform_transaction(NULL, interruptible_callback);
+    
+    num_roots = num_roots_outside_perform;
+    copy_roots(roots_outside_perform, roots);
+    
+    interruptible = 0;
+    pop_roots();
+}
+
+
+int interruptible_callback(gcptr arg1, int retry_counter)
+{
+    num_roots = num_roots_outside_perform;
+    copy_roots(roots_outside_perform, roots);
+
+    arg1 = stm_pop_root();
+    pop_roots();
+    push_roots();
+    stm_push_root(arg1);
+
+    gcptr p = run_me();
+    int restart = p == -1 ? get_rand(3) != 1 : 0;
+
+    return restart;
+}
+
+int run_me()
+{
+    gcptr p = NULL;
+    while (steps_left) {
+        steps_left--;
+        p = do_step(p);
+
+        if (p == -1)
+            return p;
+    }
+    return 0;
+}
+
+
+static sem_t done;
+static int thr_mynum = 0;
+
+void *demo(void *arg)
+{  
+    int status, i;
+    
+    stm_initialize();
+    setup_thread();
+    
+    thr_mynum++;   /* protected by being inevitable here */
+    fprintf(stderr, "THREAD STARTING\n");
+
+    run_me();
+    
+    stm_finalize();
+    
+    status = sem_post(&done);
+    assert(status == 0);
+    return NULL;
+}
+
+
+void newthread(void*(*func)(void*), void *arg)
+{
+    pthread_t th;
+    int status = pthread_create(&th, NULL, func, arg);
+    assert(status == 0);
+    pthread_detach(th);
+    printf("started new thread\n");
+}
+
+
+
+int main(void)
+{
+    int i, status;
+    
+    // seed changes daily
+    // a bit pointless for now..
+    default_seed = time(NULL) / 3600 / 24;
+    
+    for (i = 0; i < SHARED_ROOTS; i++) {
+        shared_roots[i] = allocate_pseudoprebuilt(sizeof(struct root), 
+                                                  GCTID_STRUCT_ROOT);
+    }    
+    
+    status = sem_init(&done, 0, 0);
+    assert(status == 0);
+    
+    for (i = 0; i < NUMTHREADS; i++)
+        newthread(demo, NULL);
+    
+    for (i=0; i < NUMTHREADS; i++) {
+        status = sem_wait(&done);
+        assert(status == 0);
+        printf("thread finished\n");
+    }
+    
+    return 0;
+}
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to