Bump version to 0.3.5next
[archipelago] / xseg / xtypes / xwaitq_test.c
1 /*
2  * Copyright 2013 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #include "xwaitq.h"
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <pthread.h>
39 #include <xtypes/xlock.h>
40 #include <sys/time.h>
41
42
43 volatile int cond = 0;
44 unsigned long sum = 0;
45 struct xlock lock;
46
47 int condfn(void *arg)
48 {
49         return cond;
50 }
51
52 void jobfn(void *q, void *arg)
53 {
54         unsigned long c = (unsigned long) arg;
55         xlock_acquire(&lock, c);
56         sum += c;
57         xlock_release(&lock);
58 }
59
60 int test1(unsigned long n)
61 {
62         struct xwaitq wq;
63         unsigned long i;
64         struct work *works = malloc(sizeof(struct work) * n);
65         xwaitq_init(&wq, condfn, NULL, 0);
66         cond = 0;
67         sum = 0;
68         xlock_release(&lock);
69
70         for (i = 0; i < n; i++) {
71                 works[i].job_fn = jobfn;
72                 works[i].job = 1;
73         }
74
75         for (i = 0; i < n; i++) {
76                 xwaitq_enqueue(&wq, &works[i]);
77         }
78         cond = 1;
79         xwaitq_signal(&wq);
80
81         free(works);
82         xwaitq_destroy(&wq);
83
84         return ((sum == n)? 0 : -1);
85 }
86
87 struct thread_arg{
88         struct xwaitq *wq;
89         unsigned long n;
90         unsigned long num;
91 };
92
93 void *thread_test(void *arg)
94 {
95         struct thread_arg *targ = (struct thread_arg *)arg;
96         unsigned long n = targ->n;
97         unsigned long i;
98
99         struct work *works = malloc(sizeof(struct work) * n);
100
101         for (i = 0; i < n; i++) {
102                 works[i].job_fn = jobfn;
103                 works[i].job = targ->num;
104         }
105
106         for (i = 0; i < n; i++) {
107                 xwaitq_enqueue(targ->wq, &works[i]);
108         }
109         cond = 1;
110         xwaitq_signal(targ->wq);
111
112 //      free(works);
113
114         return NULL;
115 }
116
117 int test2(unsigned long n, unsigned long nr_threads)
118 {
119         int i, r;
120         struct xwaitq wq;
121         xwaitq_init(&wq, condfn, NULL, 0);
122         cond = 0;
123         sum = 0;
124         xlock_release(&lock);
125
126         struct thread_arg *targs = malloc(sizeof(struct thread_arg)*nr_threads * n);
127         pthread_t *threads = malloc(sizeof(pthread_t) * nr_threads);
128
129         for (i = 0; i < nr_threads; i++) {
130                 targs[i].num = i+1;
131                 targs[i].n = n;
132                 targs[i].wq = &wq;
133         }
134         for (i = 0; i < nr_threads; i++) {
135                 r = pthread_create(&threads[i], NULL, thread_test, &targs[i]);
136                 if (r) {
137                         fprintf(stderr, "error pthread_create\n");
138                         return -1;
139                 }
140         }
141
142         for (i = 0; i < nr_threads; i++) {
143                 pthread_join(threads[i], NULL);
144         }
145
146
147
148         free(targs);
149         free(threads);
150         xwaitq_destroy(&wq);
151
152         unsigned long expected_sum = 0;
153         for (i = 0; i < nr_threads; i++) {
154                 expected_sum += n*(i+1);
155         }
156         return ((sum == expected_sum) ? 0 : -1);
157 }
158
159 int test3(unsigned long n, unsigned long nr_threads)
160 {
161         int i, r;
162         struct xwaitq wq;
163         xwaitq_init(&wq, condfn, NULL, XWAIT_SIGNAL_ONE);
164         cond = 0;
165         sum = 0;
166         xlock_release(&lock);
167
168         struct thread_arg *targs = malloc(sizeof(struct thread_arg)*nr_threads * n);
169         pthread_t *threads = malloc(sizeof(pthread_t) * nr_threads);
170
171         for (i = 0; i < nr_threads; i++) {
172                 targs[i].num = i+1;
173                 targs[i].n = n;
174                 targs[i].wq = &wq;
175         }
176         for (i = 0; i < nr_threads; i++) {
177                 r = pthread_create(&threads[i], NULL, thread_test, &targs[i]);
178                 if (r) {
179                         fprintf(stderr, "error pthread_create\n");
180                         return -1;
181                 }
182         }
183
184         for (i = 0; i < nr_threads; i++) {
185                 pthread_join(threads[i], NULL);
186         }
187
188
189
190         free(targs);
191         free(threads);
192         xwaitq_destroy(&wq);
193
194         unsigned long expected_sum = 0;
195         for (i = 0; i < nr_threads; i++) {
196                 expected_sum += n*(i+1);
197         }
198         return ((sum == expected_sum) ? 0 : -1);
199 }
200
201 int main(int argc, const char *argv[])
202 {
203         struct timeval start, end, tv;
204         int r;
205         int n = atoi(argv[1]);
206         int t = atoi(argv[2]);
207
208         fprintf(stderr, "Running test1\n");
209         gettimeofday(&start, NULL);
210         r = test1(n);
211         if (r < 0){
212                 fprintf(stderr, "Test1: FAILED\n");
213                 return -1;
214         }
215         gettimeofday(&end, NULL);
216         timersub(&end, &start, &tv);
217         fprintf(stderr, "Test1: PASSED\n");
218         fprintf(stderr, "Test time: %ds %dusec\n\n", (int)tv.tv_sec, (int)tv.tv_usec);
219
220         fprintf(stderr, "running test2\n");
221         gettimeofday(&start, NULL);
222         r = test2(n, t);
223         if (r < 0){
224                 fprintf(stderr, "test2: failed\n");
225                 return -1;
226         }
227         gettimeofday(&end, NULL);
228         fprintf(stderr, "test2: passed\n");
229         timersub(&end, &start, &tv);
230         fprintf(stderr, "Test time: %ds %dusec\n\n", (int)tv.tv_sec, (int)tv.tv_usec);
231
232         fprintf(stderr, "running test3\n");
233         gettimeofday(&start, NULL);
234         r = test3(n, t);
235         if (r < 0){
236                 fprintf(stderr, "test3: failed\n");
237                 return -1;
238         }
239         gettimeofday(&end, NULL);
240         fprintf(stderr, "test3: passed\n");
241         timersub(&end, &start, &tv);
242         fprintf(stderr, "Test time: %ds %dusec\n\n", (int)tv.tv_sec, (int)tv.tv_usec);
243
244         return 0;
245 }