5
* --------------------------------------------------------------------------
7
* Pthreads-win32 - POSIX Threads Library for Win32
8
* Copyright(C) 1998 John E. Bossom
9
* Copyright(C) 1999,2005 Pthreads-win32 contributors
11
* Contact Email: rpj@callisto.canberra.edu.au
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
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.
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.
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
34
* --------------------------------------------------------------------------
37
* - Stress test condition variables, mutexes, semaphores.
39
* Test Method (Validation or Falsification):
42
* Requirements Tested:
43
* - Correct accounting of semaphore and condition variable waiters.
52
* Attempting to expose race conditions in cond vars, semaphores etc.
53
* - Master attempts to signal slave close to when timeout is due.
54
* - Master and slave do battle continuously until main tells them to stop.
55
* - Afterwards, the CV must be successfully destroyed (will return an
56
* error if there are waiters (including any internal semaphore waiters,
57
* which, if there are, cannot not be real waiters).
66
* - File name, Line number, and failed expression on failure.
67
* - No output on success.
73
* - CV is successfully destroyed.
81
#include <sys/timeb.h>
84
const unsigned int ITERATIONS = 1000;
86
static pthread_t master, slave;
94
static mysig_t control = {0, PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
95
static pthread_barrier_t startBarrier, readyBarrier, holdBarrier;
96
static int timeoutCount = 0;
97
static int signalsTakenCount = 0;
98
static int signalsSent = 0;
100
static int timeout = 10;
108
* Returns abstime 'milliseconds' from 'now'.
110
* Works for: -INT_MAX <= millisecs <= INT_MAX
113
millisecondsFromNow (struct timespec * time, int millisecs)
115
struct _timeb currSysTime;
116
int64_t nanosecs, secs;
117
const int64_t NANOSEC_PER_MILLISEC = 1000000;
118
const int64_t NANOSEC_PER_SEC = 1000000000;
120
/* get current system time and add millisecs */
121
_ftime(&currSysTime);
123
secs = (int64_t)(currSysTime.time) + (millisecs / 1000);
124
nanosecs = ((int64_t) (millisecs%1000 + currSysTime.millitm)) * NANOSEC_PER_MILLISEC;
125
if (nanosecs >= NANOSEC_PER_SEC)
128
nanosecs -= NANOSEC_PER_SEC;
130
else if (nanosecs < 0)
133
nanosecs += NANOSEC_PER_SEC;
136
time->tv_nsec = (long)nanosecs;
137
time->tv_sec = (long)secs;
143
masterThread (void * arg)
145
int dither = (int) arg;
149
pthread_barrier_wait(&startBarrier);
155
assert(pthread_mutex_lock(&control.mx) == 0);
156
control.value = timeout;
157
assert(pthread_mutex_unlock(&control.mx) == 0);
160
* We are attempting to send the signal close to when the slave
161
* is due to timeout. We feel around by adding some [non-random] dither.
163
* dither is in the range 2*timeout peak-to-peak
164
* sleep time is the average of timeout plus dither.
166
* if timeout = 10 then dither = 20 and
167
* sleep millisecs is: 5 <= ms <= 15
169
* The bias value attempts to apply some negative feedback to keep
170
* the ratio of timeouts to signals taken close to 1:1.
171
* bias changes more slowly than dither so as to average more.
173
* Finally, if abs(bias) exceeds timeout then timeout is incremented.
175
if (signalsSent % timeout == 0)
177
if (timeoutCount > signalsTakenCount)
181
else if (timeoutCount < signalsTakenCount)
185
if (bias < -timeout || bias > timeout)
190
dither = (dither + 1 ) % (timeout * 2);
191
sleepTime = (timeout - bias + dither) / 2;
193
assert(pthread_cond_signal(&control.cv) == 0);
196
pthread_barrier_wait(&holdBarrier);
197
pthread_barrier_wait(&readyBarrier);
205
slaveThread (void * arg)
207
struct timespec time;
209
pthread_barrier_wait(&startBarrier);
213
assert(pthread_mutex_lock(&control.mx) == 0);
214
if (pthread_cond_timedwait(&control.cv,
216
millisecondsFromNow(&time, control.value)) == ETIMEDOUT)
224
assert(pthread_mutex_unlock(&control.mx) == 0);
226
pthread_barrier_wait(&holdBarrier);
227
pthread_barrier_wait(&readyBarrier);
239
assert(pthread_barrier_init(&startBarrier, NULL, 3) == 0);
240
assert(pthread_barrier_init(&readyBarrier, NULL, 3) == 0);
241
assert(pthread_barrier_init(&holdBarrier, NULL, 3) == 0);
243
assert(pthread_create(&master, NULL, masterThread, (void *) timeout) == 0);
244
assert(pthread_create(&slave, NULL, slaveThread, NULL) == 0);
248
pthread_barrier_wait(&startBarrier);
250
for (i = 1; !allExit; i++)
252
pthread_barrier_wait(&holdBarrier);
257
pthread_barrier_wait(&readyBarrier);
260
assert(pthread_join(slave, NULL) == 0);
261
assert(pthread_join(master, NULL) == 0);
263
printf("Signals sent = %d\nWait timeouts = %d\nSignals taken = %d\nBias = %d\nTimeout = %d\n",
271
assert(pthread_barrier_destroy(&holdBarrier) == 0);
272
assert(pthread_barrier_destroy(&readyBarrier) == 0);
273
assert(pthread_barrier_destroy(&startBarrier) == 0);
274
assert(pthread_cond_destroy(&control.cv) == 0);
275
assert(pthread_mutex_destroy(&control.mx) == 0);