Sourceware Bugzilla – Attachment 5947 Details for
Bug 13165
pthread_cond_wait() can consume a signal that was sent before it started waiting
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Simpler test, converted to pure C
condvar_race_2.c (text/plain), 5.59 KB, created by
Rich Felker
on 2011-09-28 02:08:00 UTC
(
hide
)
Description:
Simpler test, converted to pure C
Filename:
MIME Type:
Creator:
Rich Felker
Created:
2011-09-28 02:08:00 UTC
Size:
5.59 KB
patch
obsolete
>#include <stdio.h> >#include <stdbool.h> >#include <pthread.h> >#include <sched.h> >#include <sys/time.h> >#include <time.h> >#include <errno.h> > >const int maxWaiterThreadsCount = 30; >const bool releaseMutexBetweenSignals = false; >const int waitTimeSec = 15; > >bool exitProgram; >int threadsCount; >int beforeWaitersCount; >int afterWaitersCount; >int signalsSentCount; >int beforeWaitersWokenCount; >int afterWaitersWokenCount; >int iterationCount; > >pthread_mutex_t mutex; >pthread_cond_t testCond; > >void* ThreadMain(void* data) >{ > // Wait for the main thread to create all waiter threads > pthread_mutex_lock(&mutex); > > while (!exitProgram) { > // 1. Remember which is the current test iteration > int currIterationCount = iterationCount; > > // 2. Check if we are starting the wait before all signals have been sent. > bool beforeAllSignalsSent = signalsSentCount < threadsCount; > > // 3. Count the thread towards the appropriate group of waiters (before/after > // all signals are sent) > if (beforeAllSignalsSent) { > ++beforeWaitersCount; > } else { > ++afterWaitersCount; > } > > // 4. Wait on the condition variable. > pthread_cond_wait(&testCond, &mutex); > > // 5. If the iteration count has changed, start over > if (currIterationCount != iterationCount) { > continue; > } > > // 6. Count the woken thread towards the appropriate group of woken threads (the > // same group as step 2). > if (beforeAllSignalsSent) { > ++beforeWaitersWokenCount; > } else { > ++afterWaitersWokenCount; > } > } > pthread_mutex_unlock(&mutex); > pthread_exit(NULL); >} > >int main() >{ >// 1. Test setup: > // 1.1. Initialize the mutex and the condition variable > pthread_mutex_init(&mutex, NULL); > pthread_cond_init(&testCond, NULL); > > // 1.2. > > exitProgram = false; > > // 1.3. Create some waiter threads. All waiters will imediately block on the mutex > pthread_mutex_lock(&mutex); > > for (threadsCount = 0; threadsCount < maxWaiterThreadsCount; ++threadsCount) { > pthread_t thread; > > if (pthread_create(&thread, NULL, ThreadMain, NULL) != 0) { > break; > } > > pthread_detach(thread); > } > > printf("Created %d threads.\n", threadsCount); >// cout << "Created " << threadsCount << " threads." << endl; > >// 2. Test body. Count the test body iterations to help waiters detect when a >// new iteration has started > for (iterationCount = 0; !exitProgram; ++iterationCount) { > // 2.1. Reset the counters > beforeWaitersCount = 0; > afterWaitersCount = 0; > beforeWaitersWokenCount = 0; > afterWaitersWokenCount = 0; > signalsSentCount = 0; > > // 2.2. Wait for all waiters to block on the condition variable > while (beforeWaitersCount < threadsCount) { > pthread_mutex_unlock(&mutex); > sched_yield(); > pthread_mutex_lock(&mutex); > } > > // 2.3. Send as many inidividual signals as there are waiter threads > for (; signalsSentCount < threadsCount; ++signalsSentCount) { > pthread_cond_signal(&testCond); > > if (releaseMutexBetweenSignals) { > pthread_mutex_unlock(&mutex); > sched_yield(); > pthread_mutex_lock(&mutex); > } > } > > // 2.4. Wait for at least two threads to block again after the signals were > // sent. But if we were releasing the mutex between signals it is possible > // that too much threads woke up and reentered the wait so we need to make > // sure that there are enough threads that havent woken yet. > if (signalsSentCount - beforeWaitersWokenCount > 2) { > while (afterWaitersCount < 2) { > pthread_mutex_unlock(&mutex); > sched_yield(); > pthread_mutex_lock(&mutex); > } > } > > // 2.5. Send a single signal > pthread_cond_signal(&testCond); > > > // 2.6. Wait for a predefined time for at least signalsSentCount 'before' > // waiters to wake up. > time_t endTime; > time_t startTime = time(&endTime); > while (beforeWaitersWokenCount < signalsSentCount) { > pthread_mutex_unlock(&mutex); > sched_yield(); > pthread_mutex_lock(&mutex); > > if (time(&endTime) - startTime > waitTimeSec) { > break; > } > } > > // 2.7. If some threads that should have been unblocked by the first > // signalsSentCount signals have remained blocked, report that the > // race was hit > if (beforeWaitersWokenCount < signalsSentCount) { > printf("Race hit.\n\tWaited:\t\t%ds\n\tFailed to wake:\t%d\n\tExtra woken:\t%d\n", > endTime-startTime, signalsSentCount-beforeWaitersWokenCount, > afterWaitersWokenCount-1); >// cout << "Race hit." << endl >// << "\tWaited:\t\t" << endTime - startTime << "s" << endl >// << "\tFailed to wake\t: " << signalsSentCount - beforeWaitersWokenCount << endl >// << "\tExtra woken:\t" << afterWaitersWokenCount - 1 << endl; > // Notify all waiters that they should exit > exitProgram = true; > } else { > printf("Race not hit.\n"); >// cout << "Race not hit." << endl; > } > > // 2.8. Send a broadcast to let all waiters move to the start of the next > // test iteration or exit > pthread_cond_broadcast(&testCond); > } > > pthread_mutex_unlock(&mutex); > pthread_exit(NULL); >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 13165
:
5945
|
5946
| 5947