2 /* Simple pthread example using pthread_mutex to ensure mutual exclusion */
3 /* This corrects the bug from raceexample.c */
4 /* To compile me for Linux, type: gcc -o filename filename.c -lpthread */
5 /* To execute, type: filename */
10 #include <sys/time.h> //getrusage, gettimeofday
11 #include <sys/resource.h>
13 void * simplemux1(void *);
14 void * simplemux2(void *);
15 void * simplemux3(void *);
16 void * simplemux4(void *);
17 void * simplemux5(void *);
18 void * simplespin(void *);
19 void * simplespins(void *);
20 void * simplecas1(void *);
21 void * simplecas2(void *);
22 void * simplecas3(void *);
23 void * simplecas4(void *);
24 void * simplecas5(void *);
25 void * simplena(void *);
27 int NumThreads
,SumCount
;
29 pthread_mutex_t mut1
=PTHREAD_MUTEX_INITIALIZER
;
30 pthread_mutex_t mut2
=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
31 pthread_mutex_t mut3
=PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
;
32 pthread_mutex_t mut4
=PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
;
33 pthread_mutex_t mut5
={ { 0, 0, 0, 0, PTHREAD_MUTEX_FAST_NP
, 0, { 0, 0 } } };
34 pthread_spinlock_t spin
,spins
;
36 struct timeval __g_timeofday_start
, __g_timeofday_end
, __g_timeofday_diff
,\
37 __g_resource_usage_tmp
,__g_resource_usage_other_time
;
38 struct rusage __g_resource_usage
;
40 #define G_TIMER_START \
41 gettimeofday(&__g_timeofday_start,NULL)
45 getrusage(RUSAGE_SELF, &__g_resource_usage);\
46 gettimeofday(&__g_timeofday_end,NULL);\
47 timersub(&__g_timeofday_end,&__g_timeofday_start,&__g_timeofday_diff);\
50 #define G_TIMER_PRINT \
52 "U: %ld.%06ld, S: %ld.%06ld, R: %ld.%06ld (s)\n",\
53 __g_resource_usage.ru_utime.tv_sec, __g_resource_usage.ru_utime.tv_usec,\
54 __g_resource_usage.ru_stime.tv_sec, __g_resource_usage.ru_stime.tv_usec,\
55 __g_timeofday_diff.tv_sec, __g_timeofday_diff.tv_usec);
57 int main( int argc
, char *argv
[] ) {
61 printf("Usage: %s threads to_count\n",argv
[0]);
64 SumCount
=atoi(argv
[2]);
65 NumThreads
=atoi(argv
[1]);
66 fprintf(stderr
, "Threads:%d, To_Count:%d\n\n",NumThreads
,SumCount
);
68 pthread_t
*tid
=malloc(NumThreads
*sizeof(pthread_t
)); /* array of thread IDs */
69 //pthread_mutex_init(&mut1, NULL);
70 pthread_spin_init(&spin
, PTHREAD_PROCESS_PRIVATE
);
71 pthread_spin_init(&spins
, PTHREAD_PROCESS_SHARED
);
75 for (i
=0; i
<NumThreads
; i
++) {
76 pthread_create(&tid
[i
], NULL
, simplena
, NULL
);
78 for ( i
= 0; i
< NumThreads
; i
++)
79 pthread_join(tid
[i
], NULL
);
80 fprintf(stderr
, "Non-lock:\n[%d]%d ", i
, bignum
);
87 for (i
=0; i
<NumThreads
; i
++) {
88 pthread_create(&tid
[i
], NULL
, simplespin
, NULL
);
90 for ( i
= 0; i
< NumThreads
; i
++)
91 pthread_join(tid
[i
], NULL
);
92 fprintf(stderr
, "Spin-lock:\n[%d]%d PROCESS_PRIVATE ", i
, bignum
);
98 for (i
=0; i
<NumThreads
; i
++) {
99 pthread_create(&tid
[i
], NULL
, simplespins
, NULL
);
101 for ( i
= 0; i
< NumThreads
; i
++)
102 pthread_join(tid
[i
], NULL
);
103 fprintf(stderr
, "[%d]%d PROCESS_SHARED ", i
, bignum
);
109 for (i
=0; i
<NumThreads
; i
++) {
110 pthread_create(&tid
[i
], NULL
, simplemux1
, NULL
);
112 for ( i
= 0; i
< NumThreads
; i
++)
113 pthread_join(tid
[i
], NULL
);
114 fprintf(stderr
, "Mux-lock:\n[%d]%d NULL ", i
, bignum
);
120 for (i
=0; i
<NumThreads
; i
++) {
121 pthread_create(&tid
[i
], NULL
, simplemux2
, NULL
);
123 for ( i
= 0; i
< NumThreads
; i
++)
124 pthread_join(tid
[i
], NULL
);
125 fprintf(stderr
, "[%d]%d RECURSIVE ", i
, bignum
);
130 for (i
=0; i
<NumThreads
; i
++) {
131 pthread_create(&tid
[i
], NULL
, simplemux3
, NULL
);
133 for ( i
= 0; i
< NumThreads
; i
++)
134 pthread_join(tid
[i
], NULL
);
135 fprintf(stderr
, "[%d]%d ERRORCHECK ", i
, bignum
);
140 for (i
=0; i
<NumThreads
; i
++) {
141 pthread_create(&tid
[i
], NULL
, simplemux4
, NULL
);
143 for ( i
= 0; i
< NumThreads
; i
++)
144 pthread_join(tid
[i
], NULL
);
145 fprintf(stderr
, "[%d]%d ADAPTIVE ", i
, bignum
);
150 for (i
=0; i
<NumThreads
; i
++) {
151 pthread_create(&tid
[i
], NULL
, simplemux5
, NULL
);
153 for ( i
= 0; i
< NumThreads
; i
++)
154 pthread_join(tid
[i
], NULL
);
155 fprintf(stderr
, "[%d]%d FAST ", i
, bignum
);
161 for (i
=0; i
<NumThreads
; i
++) {
162 pthread_create(&tid
[i
], NULL
, simplecas1
, NULL
);
164 for ( i
= 0; i
< NumThreads
; i
++)
165 pthread_join(tid
[i
], NULL
);
166 fprintf(stderr
, "Atomic:\n[%d]%d fetch_and_add ", i
, bignum
);
172 for (i
=0; i
<NumThreads
; i
++) {
173 pthread_create(&tid
[i
], NULL
, simplecas2
, NULL
);
175 for ( i
= 0; i
< NumThreads
; i
++)
176 pthread_join(tid
[i
], NULL
);
177 fprintf(stderr
, "[%d]%d add_and_fetch ", i
, bignum
);
183 for (i
=0; i
<NumThreads
; i
++) {
184 pthread_create(&tid
[i
], NULL
, simplecas3
, NULL
);
186 for ( i
= 0; i
< NumThreads
; i
++)
187 pthread_join(tid
[i
], NULL
);
188 fprintf(stderr
, "[%d]%d val cmpxchg ", i
, bignum
);
194 for (i
=0; i
<NumThreads
; i
++) {
195 pthread_create(&tid
[i
], NULL
, simplecas4
, NULL
);
197 for ( i
= 0; i
< NumThreads
; i
++)
198 pthread_join(tid
[i
], NULL
);
199 fprintf(stderr
, "[%d]%d bool cmpxchg ", i
, bignum
);
206 void * simplemux1(void * parm
)
209 for(i
=0;i
<SumCount
;i
++) {
210 pthread_mutex_lock(&mut1
);
211 bignum
++; /* critical section */
212 pthread_mutex_unlock(&mut1
);
217 void * simplemux2(void * parm
)
220 for(i
=0;i
<SumCount
;i
++) {
221 pthread_mutex_lock(&mut2
);
222 bignum
++; /* critical section */
223 pthread_mutex_unlock(&mut2
);
228 void * simplemux3(void * parm
)
231 for(i
=0;i
<SumCount
;i
++) {
232 pthread_mutex_lock(&mut3
);
233 bignum
++; /* critical section */
234 pthread_mutex_unlock(&mut3
);
239 void * simplemux4(void * parm
)
242 for(i
=0;i
<SumCount
;i
++) {
243 pthread_mutex_lock(&mut4
);
244 bignum
++; /* critical section */
245 pthread_mutex_unlock(&mut4
);
250 void * simplemux5(void * parm
)
253 for(i
=0;i
<SumCount
;i
++) {
254 pthread_mutex_lock(&mut5
);
255 bignum
++; /* critical section */
256 pthread_mutex_unlock(&mut5
);
261 void * simplespin(void * parm
)
264 for(i
=0;i
<SumCount
;i
++) {
265 pthread_spin_lock(&spin
);
266 bignum
++; /* critical section */
267 pthread_spin_unlock(&spin
);
272 void * simplespins(void * parm
)
275 for(i
=0;i
<SumCount
;i
++) {
276 pthread_spin_lock(&spins
);
277 bignum
++; /* critical section */
278 pthread_spin_unlock(&spins
);
283 void * simplecas1(void * parm
)
286 for(i
=0;i
<SumCount
;i
++) {
287 __sync_fetch_and_add(&bignum
,1); /* critical section */
291 void * simplecas2(void * parm
)
294 for(i
=0;i
<SumCount
;i
++) {
295 __sync_add_and_fetch(&bignum
,1); /* critical section */
299 void * simplecas3(void * parm
)
302 for(i
=0;i
<SumCount
;i
++) {
306 ret
=__sync_val_compare_and_swap(&bignum
,old
,old
+1);
307 //if (ret!=old) printf("O:%d R:%d\n",old,ret);
312 void * simplecas4(void * parm
)
315 for(i
=0;i
<SumCount
;i
++) {
319 } while (!__sync_bool_compare_and_swap(&bignum
,old
,old
+1));
324 //#pragma GCC optimize 0
325 void * simplena(void * parm
)
328 for(i
=0;i
<SumCount
;++i
) {
329 ++bignum
; /* critical section */
333 //#pragma GCC optimize 3