• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * benchtest1.c
3  *
4  *
5  * --------------------------------------------------------------------------
6  *
7  *      Pthreads-win32 - POSIX Threads Library for Win32
8  *      Copyright(C) 1998 John E. Bossom
9  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
10  *
11  *      Contact Email: rpj@callisto.canberra.edu.au
12  *
13  *      The current list of contributors is contained
14  *      in the file CONTRIBUTORS included with the source
15  *      code distribution. The list can also be seen at the
16  *      following World Wide Web location:
17  *      http://sources.redhat.com/pthreads-win32/contributors.html
18  *
19  *      This library is free software; you can redistribute it and/or
20  *      modify it under the terms of the GNU Lesser General Public
21  *      License as published by the Free Software Foundation; either
22  *      version 2 of the License, or (at your option) any later version.
23  *
24  *      This library is distributed in the hope that it will be useful,
25  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27  *      Lesser General Public License for more details.
28  *
29  *      You should have received a copy of the GNU Lesser General Public
30  *      License along with this library in the file COPYING.LIB;
31  *      if not, write to the Free Software Foundation, Inc.,
32  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
33  *
34  * --------------------------------------------------------------------------
35  *
36  * Measure time taken to complete an elementary operation.
37  *
38  * - Mutex
39  *   Two threads iterate over lock/unlock for each mutex type.
40  *   The two threads are forced into lock-step using two mutexes,
41  *   forcing the threads to block on each lock operation. The
42  *   time measured is therefore the worst case senario.
43  */
44 
45 #include "test.h"
46 #include <sys/timeb.h>
47 
48 #ifdef __GNUC__
49 #include <stdlib.h>
50 #endif
51 
52 #include "benchtest.h"
53 
54 #define PTW32_MUTEX_TYPES
55 #define ITERATIONS      100000L
56 
57 pthread_mutex_t gate1, gate2;
58 old_mutex_t ox1, ox2;
59 CRITICAL_SECTION cs1, cs2;
60 pthread_mutexattr_t ma;
61 long durationMilliSecs;
62 long overHeadMilliSecs = 0;
63 struct _timeb currSysTimeStart;
64 struct _timeb currSysTimeStop;
65 pthread_t worker;
66 int running = 0;
67 
68 #define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
69                                                - (_TStart.time*1000+_TStart.millitm))
70 
71 /*
72  * Dummy use of j, otherwise the loop may be removed by the optimiser
73  * when doing the overhead timing with an empty loop.
74  */
75 #define TESTSTART \
76   { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
77 
78 #define TESTSTOP \
79   }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
80 
81 
82 void *
overheadThread(void * arg)83 overheadThread(void * arg)
84 {
85   do
86     {
87       sched_yield();
88     }
89   while (running);
90 
91   return NULL;
92 }
93 
94 
95 void *
oldThread(void * arg)96 oldThread(void * arg)
97 {
98   do
99     {
100       (void) old_mutex_lock(&ox1);
101       (void) old_mutex_lock(&ox2);
102       (void) old_mutex_unlock(&ox1);
103       sched_yield();
104       (void) old_mutex_unlock(&ox2);
105     }
106   while (running);
107 
108   return NULL;
109 }
110 
111 void *
workerThread(void * arg)112 workerThread(void * arg)
113 {
114   do
115     {
116       (void) pthread_mutex_lock(&gate1);
117       (void) pthread_mutex_lock(&gate2);
118       (void) pthread_mutex_unlock(&gate1);
119       sched_yield();
120       (void) pthread_mutex_unlock(&gate2);
121     }
122   while (running);
123 
124   return NULL;
125 }
126 
127 void *
CSThread(void * arg)128 CSThread(void * arg)
129 {
130   do
131     {
132       EnterCriticalSection(&cs1);
133       EnterCriticalSection(&cs2);
134       LeaveCriticalSection(&cs1);
135       sched_yield();
136       LeaveCriticalSection(&cs2);
137     }
138   while (running);
139 
140   return NULL;
141 }
142 
143 void
runTest(char * testNameString,int mType)144 runTest (char * testNameString, int mType)
145 {
146 #ifdef PTW32_MUTEX_TYPES
147   assert(pthread_mutexattr_settype(&ma, mType) == 0);
148 #endif
149   assert(pthread_mutex_init(&gate1, &ma) == 0);
150   assert(pthread_mutex_init(&gate2, &ma) == 0);
151   assert(pthread_mutex_lock(&gate1) == 0);
152   assert(pthread_mutex_lock(&gate2) == 0);
153   running = 1;
154   assert(pthread_create(&worker, NULL, workerThread, NULL) == 0);
155   TESTSTART
156   (void) pthread_mutex_unlock(&gate1);
157   sched_yield();
158   (void) pthread_mutex_unlock(&gate2);
159   (void) pthread_mutex_lock(&gate1);
160   (void) pthread_mutex_lock(&gate2);
161   TESTSTOP
162   running = 0;
163   assert(pthread_mutex_unlock(&gate2) == 0);
164   assert(pthread_mutex_unlock(&gate1) == 0);
165   assert(pthread_join(worker, NULL) == 0);
166   assert(pthread_mutex_destroy(&gate2) == 0);
167   assert(pthread_mutex_destroy(&gate1) == 0);
168   durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
169   printf( "%-45s %15ld %15.3f\n",
170 	    testNameString,
171           durationMilliSecs,
172           (float) durationMilliSecs * 1E3 / ITERATIONS / 4   /* Four locks/unlocks per iteration */);
173 }
174 
175 
176 int
main(int argc,char * argv[])177 main (int argc, char *argv[])
178 {
179   assert(pthread_mutexattr_init(&ma) == 0);
180 
181   printf( "=============================================================================\n");
182   printf( "\nLock plus unlock on a locked mutex.\n");
183   printf("%ld iterations, four locks/unlocks per iteration.\n\n", ITERATIONS);
184 
185   printf( "%-45s %15s %15s\n",
186 	    "Test",
187 	    "Total(msec)",
188 	    "average(usec)");
189   printf( "-----------------------------------------------------------------------------\n");
190 
191   /*
192    * Time the loop overhead so we can subtract it from the actual test times.
193    */
194 
195   running = 1;
196   assert(pthread_create(&worker, NULL, overheadThread, NULL) == 0);
197   TESTSTART
198   sched_yield();
199   sched_yield();
200   TESTSTOP
201   running = 0;
202   assert(pthread_join(worker, NULL) == 0);
203   durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
204   overHeadMilliSecs = durationMilliSecs;
205 
206 
207   InitializeCriticalSection(&cs1);
208   InitializeCriticalSection(&cs2);
209   EnterCriticalSection(&cs1);
210   EnterCriticalSection(&cs2);
211   running = 1;
212   assert(pthread_create(&worker, NULL, CSThread, NULL) == 0);
213   TESTSTART
214   LeaveCriticalSection(&cs1);
215   sched_yield();
216   LeaveCriticalSection(&cs2);
217   EnterCriticalSection(&cs1);
218   EnterCriticalSection(&cs2);
219   TESTSTOP
220   running = 0;
221   LeaveCriticalSection(&cs2);
222   LeaveCriticalSection(&cs1);
223   assert(pthread_join(worker, NULL) == 0);
224   DeleteCriticalSection(&cs2);
225   DeleteCriticalSection(&cs1);
226   durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
227   printf( "%-45s %15ld %15.3f\n",
228 	    "Simple Critical Section",
229           durationMilliSecs,
230           (float) durationMilliSecs * 1E3 / ITERATIONS / 4 );
231 
232 
233   old_mutex_use = OLD_WIN32CS;
234   assert(old_mutex_init(&ox1, NULL) == 0);
235   assert(old_mutex_init(&ox2, NULL) == 0);
236   assert(old_mutex_lock(&ox1) == 0);
237   assert(old_mutex_lock(&ox2) == 0);
238   running = 1;
239   assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
240   TESTSTART
241   (void) old_mutex_unlock(&ox1);
242   sched_yield();
243   (void) old_mutex_unlock(&ox2);
244   (void) old_mutex_lock(&ox1);
245   (void) old_mutex_lock(&ox2);
246   TESTSTOP
247   running = 0;
248   assert(old_mutex_unlock(&ox1) == 0);
249   assert(old_mutex_unlock(&ox2) == 0);
250   assert(pthread_join(worker, NULL) == 0);
251   assert(old_mutex_destroy(&ox2) == 0);
252   assert(old_mutex_destroy(&ox1) == 0);
253   durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
254   printf( "%-45s %15ld %15.3f\n",
255 	    "Old PT Mutex using a Critical Section (WNT)",
256           durationMilliSecs,
257           (float) durationMilliSecs * 1E3 / ITERATIONS / 4);
258 
259 
260   old_mutex_use = OLD_WIN32MUTEX;
261   assert(old_mutex_init(&ox1, NULL) == 0);
262   assert(old_mutex_init(&ox2, NULL) == 0);
263   assert(old_mutex_lock(&ox1) == 0);
264   assert(old_mutex_lock(&ox2) == 0);
265   running = 1;
266   assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
267   TESTSTART
268   (void) old_mutex_unlock(&ox1);
269   sched_yield();
270   (void) old_mutex_unlock(&ox2);
271   (void) old_mutex_lock(&ox1);
272   (void) old_mutex_lock(&ox2);
273   TESTSTOP
274   running = 0;
275   assert(old_mutex_unlock(&ox1) == 0);
276   assert(old_mutex_unlock(&ox2) == 0);
277   assert(pthread_join(worker, NULL) == 0);
278   assert(old_mutex_destroy(&ox2) == 0);
279   assert(old_mutex_destroy(&ox1) == 0);
280   durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
281   printf( "%-45s %15ld %15.3f\n",
282 	    "Old PT Mutex using a Win32 Mutex (W9x)",
283           durationMilliSecs,
284           (float) durationMilliSecs * 1E3 / ITERATIONS / 4);
285 
286   printf( ".............................................................................\n");
287 
288   /*
289    * Now we can start the actual tests
290    */
291 #ifdef PTW32_MUTEX_TYPES
292   runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
293 
294   runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
295 
296   runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
297 
298   runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
299 #else
300   runTest("Blocking locks", 0);
301 #endif
302 
303   printf( "=============================================================================\n");
304   /*
305    * End of tests.
306    */
307 
308   pthread_mutexattr_destroy(&ma);
309 
310   return 0;
311 }
312