Created SILC Runtime Toolkit git repository Part II.
[runtime.git] / lib / silcutil / tests / test_silcmutex.c
1 /* Locking performance tests.  Gives locsk&unlocks/second. */
2 /* Version 1.0 */
3
4 #include "silcruntime.h"
5
6 typedef struct {
7   SilcThread thread;
8   SilcInt64 time;
9 } Context;
10
11 #define MAX_ROUND 8
12 #define MAX_MUL 4
13 #define MAX_THREADS 4
14 #define MAX_LOCKS 471234567
15
16 SilcMutex mutex;
17 SilcUInt64 cpu_freq = 0;
18 int max_locks, max_locks2;
19 SilcTimerStruct timer;
20
21 #define rdtsc() silc_timer_tick(&timer, FALSE)
22
23 void *mutex_thread(void *context)
24 {
25   Context *c = context;
26   SilcInt64 s;
27   register int i;
28
29   s = rdtsc();
30   for (i = 0; i < max_locks; i++) {
31     silc_mutex_lock(mutex);
32     silc_mutex_unlock(mutex);
33   }
34   c->time = rdtsc() - s;
35   c->time /= cpu_freq;
36
37   return NULL;
38 }
39
40 SilcUInt64 hval;
41 SilcUInt64 hval2;
42 SilcUInt64 hval3;
43
44 void *mutex_thread_hold(void *context)
45 {
46   Context *c = context;
47   SilcInt64 s;
48   register int i;
49
50   s = rdtsc();
51   for (i = 0; i < max_locks / 4; i++) {
52     silc_mutex_lock(mutex);
53     hval2 = i;
54     hval3 = 0;
55     hval++;
56     hval3 = hval2 + i;
57     hval += hval2;
58     hval3 += hval;
59     if (silc_unlikely(hval3 != hval2 + i + hval)) {
60       fprintf(stderr, "MUTEX CORRUPT 1\n");
61       exit(1);
62     }
63     if (silc_unlikely(hval2 != i)) {
64       fprintf(stderr, "MUTEX CORRUPT 2 (%llu != %d)\n", hval2, i);
65       exit(1);
66     }
67     silc_mutex_unlock(mutex);
68   }
69   c->time = rdtsc() - s;
70   c->time /= cpu_freq;
71
72   return NULL;
73 }
74
75 int main(int argc, char **argv)
76 {
77   Context c[MAX_THREADS * MAX_MUL];
78   SilcInt64 val;
79   int k, i, j, o = 0;
80   SilcBool success;
81
82   silc_timer_synchronize(&timer);
83   val = rdtsc();
84   sleep(1);
85   val = rdtsc() - val;
86   val /= 1000;                  /* Gives us milliseconds */
87   cpu_freq = val;
88   fprintf(stderr, "CPU frequency: %llu\n", val);
89
90   max_locks = MAX_LOCKS;
91
92   fprintf(stderr, "lock/unlock per second\n");
93
94   for (j = 0; j < MAX_ROUND; j++) {
95     for (i = 0; i < 1; i++)
96       c[i].thread = silc_thread_create(mutex_thread, &c[i], TRUE);
97
98     val = 0;
99     for (i = 0; i < 1; i++) {
100       silc_thread_wait(c[i].thread, NULL);
101       val += c[i].time;
102     }
103     fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
104                       (1000LL * max_locks * 1) / val, 1);
105
106     if (o == 0) {
107       /* If MAX_LOCKS is too large for this CPU, optimize.  We don't want to
108          wait a whole day for this test. */
109       if ((SilcInt64)(max_locks / 10) >
110           (SilcInt64)((1000LL * max_locks) / val))
111         max_locks /= 10;
112       o = 1;
113     }
114   }
115   puts("");
116
117   max_locks2 = max_locks;
118   for (k = 0; k < MAX_MUL; k++) {
119     sleep(16);
120     max_locks = max_locks2 / (k + 1);
121     for (j = 0; j < MAX_ROUND; j++) {
122       for (i = 0; i < MAX_THREADS * (k + 1); i++)
123         c[i].thread = silc_thread_create(mutex_thread, &c[i], TRUE);
124
125       val = 0;
126       for (i = 0; i < MAX_THREADS * (k + 1); i++) {
127         silc_thread_wait(c[i].thread, NULL);
128         val += c[i].time;
129       }
130       fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
131                       (1000LL * max_locks * (MAX_THREADS * (k + 1))) / val,
132                       MAX_THREADS * (k + 1));
133     }
134     puts("");
135   }
136   max_locks = max_locks2;
137
138   fprintf(stderr, "Spinning/holding lock, lock/unlock per second\n");
139
140   max_locks /= 2;
141   sleep(5);
142   for (j = 0; j < MAX_ROUND / 2; j++) {
143     for (i = 0; i < 1; i++)
144       c[i].thread = silc_thread_create(mutex_thread_hold, &c[i], TRUE);
145
146     val = 0;
147     for (i = 0; i < 1; i++) {
148       silc_thread_wait(c[i].thread, NULL);
149       val += c[i].time;
150     }
151     fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
152                       (1000LL * (max_locks / 4) * 1) / val, 1);
153   }
154   puts("");
155
156   max_locks2 = max_locks;
157   max_locks2 /= 2;
158   for (k = 0; k < MAX_MUL; k++) {
159     sleep(2);
160     max_locks = max_locks2 / (k + 1);
161     for (j = 0; j < MAX_ROUND / 2; j++) {
162       hval = hval2 = 1;
163       for (i = 0; i < MAX_THREADS * (k + 1); i++)
164         c[i].thread = silc_thread_create(mutex_thread_hold, &c[i], TRUE);
165
166       val = 0;
167       for (i = 0; i < MAX_THREADS * (k + 1); i++) {
168         silc_thread_wait(c[i].thread, NULL);
169         val += c[i].time;
170       }
171       fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
172                       (1000LL * (max_locks / 4) *
173                        (MAX_THREADS * (k + 1))) / val,
174                       MAX_THREADS * (k + 1));
175     }
176     puts("");
177   }
178
179   success = TRUE;
180
181   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
182
183   return !success;
184 }