remove double export of xseg symbols
[archipelago] / xseg / xtypes / xq_lock_test.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include <pthread.h>
6 #include <sys/time.h>
7 #include <assert.h>
8 #include <math.h>
9
10 #include "xlock.h"
11
12 struct thread_data {
13     long loops;
14     struct xlock *lock;
15     long *counter;
16     int id;
17 };
18
19 void *race_thread(void *arg)
20 {
21     struct thread_data *th = arg;
22     long loops = th->loops;
23     struct xlock *lock = th->lock;
24     long *counter = th->counter;
25     unsigned long serial = 0, oldserial = 0, total = 0, maxdiff = 0, diff = 0;
26     double totaldiff = 0.0;
27     unsigned long *diffstat;
28     long i;
29
30     diffstat = calloc((int)log2(loops), sizeof(unsigned long));
31     if (!diffstat) {
32         perror("malloc");
33         return NULL;
34     }
35
36     oldserial = xlock_acquire(lock, 1);
37     xlock_release(lock);
38
39     printf("%d: starting at %lu\n", th->id, oldserial);
40     for (i = 0; i < loops; i++) {
41         //if ((i & 15) == 0)
42         //printf("%d: %lu\n", th->id, i);
43         asm volatile ("#boo");
44         serial = xlock_acquire(lock, 1);
45         asm volatile ("#bee");
46         //serial = oldserial +1;
47         (*counter) ++;
48         diff = serial - oldserial;
49         oldserial = serial;
50         if (diff > maxdiff)
51             maxdiff = diff;
52         diffstat[(int)log2(diff)] ++;
53         if (diff > 1) {
54             total += 1;
55             totaldiff += diff;
56         }
57         xlock_release(lock);
58     }
59
60     xlock_acquire(lock, 1);
61     printf("%d: serial %lu, avediff: %.0lf/%lu = %lf maxdiff: %lu\n",
62             th->id, serial, totaldiff, total, totaldiff/total, maxdiff);
63     printf("stats:\n");
64     for (i = 0; i < (int)log2(loops); i++)
65         printf("    %012lu: %lu\n", (unsigned long)powl(2, i), diffstat[i]);
66     xlock_release(lock);
67     return NULL;
68 }
69
70 int error(const char *msg) {
71     perror(msg);
72     return 1;
73 }
74
75 long lock_race(long nr_threads, long loops, struct xlock *lock, long *counter)
76 {
77     struct thread_data *th = malloc(nr_threads * sizeof(struct thread_data));
78     long t, r;
79     if (!th)
80         return error("malloc");
81
82     pthread_t *threads = malloc(nr_threads * sizeof(pthread_t));
83     if (!threads)
84         return error("malloc");
85
86     for (t = 0; t < nr_threads; t++) {
87          th[t].id = t;
88          th[t].loops = loops;
89          th[t].counter = counter;
90          th[t].lock = lock;
91     }
92
93     for (t = 0; t < nr_threads; t++) {
94          r = pthread_create(&threads[t], NULL, race_thread, &th[t]);
95          if (r)
96             return error("pthread_create");
97     }
98
99     for (t = 0; t < nr_threads; t++) {
100          pthread_join(threads[t], NULL);
101     }
102
103     return nr_threads * loops - *counter;
104 }
105
106 struct xlock lock;
107 long counter;
108
109 int main(int argc, char **argv)
110 {
111     long loops, nr_threads, r;
112
113     if (argc < 3) {
114         printf("Usage: xlock_test <nr_threads> <nr_loops>\n");
115         return 1;
116     }
117
118     nr_threads = atoi(argv[1]);
119     if (nr_threads < 0) nr_threads = 2;
120     loops = atol(argv[2]);
121     if (loops < 0) loops = 1000;
122
123     struct timeval tv0, tv1;
124     gettimeofday(&tv0, NULL);
125     r = lock_race(nr_threads, loops, &lock, &counter);
126     gettimeofday(&tv1, NULL);
127     double seconds = tv1.tv_sec + tv1.tv_usec/1000000.0 - tv0.tv_sec - tv0.tv_usec / 1000000.0;
128     printf("lock race complete with %ld errors in %lf seconds\n", r, seconds);
129     if (r)
130         return r;
131
132     return 0;
133 }