| 108 | } |
| 109 | |
| 110 | int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex) |
| 111 | { |
| 112 | int last_waiter; |
| 113 | |
| 114 | EnterCriticalSection(&cond->waiters_lock); |
| 115 | cond->waiters++; |
| 116 | LeaveCriticalSection(&cond->waiters_lock); |
| 117 | /* |
| 118 | * Unlock external mutex and wait for signal. |
| 119 | * NOTE: we've held mutex locked long enough to increment |
| 120 | * waiters count above, so there's no problem with |
| 121 | * leaving mutex unlocked before we wait on semaphore. |
| 122 | */ |
| 123 | LeaveCriticalSection(mutex); |
| 124 | |
| 125 | /* let's wait - ignore return value */ |
| 126 | WaitForSingleObject(cond->sema, INFINITE); |
| 127 | |
| 128 | /* |
| 129 | * Decrease waiters count. If we are the last waiter, then we must |
| 130 | * notify the broadcasting thread that it can continue. |
| 131 | * But if we continued due to cond_signal, we do not have to do that |
| 132 | * because the signaling thread knows that only one waiter continued. |
| 133 | */ |
| 134 | EnterCriticalSection(&cond->waiters_lock); |
| 135 | cond->waiters--; |
| 136 | last_waiter = cond->was_broadcast && cond->waiters == 0; |
| 137 | LeaveCriticalSection(&cond->waiters_lock); |
| 138 | if (last_waiter) { |
| 139 | /* |
| 140 | * cond_broadcast was issued while mutex was held. This means |
| 141 | * that all other waiters have continued, but are contending |
| 142 | * for the mutex at the end of this function because the |
| 143 | * broadcasting thread did not leave cond_broadcast, yet. |
| 144 | * (This is so that it can be sure that each waiter has |
| 145 | * consumed exactly one slice of the semaphor.) |
| 146 | * The last waiter must tell the broadcasting thread that it |
| 147 | * can go on. |
| 148 | */ |
| 149 | SetEvent(cond->continue_broadcast); |
| 150 | /* |
| 151 | * Now we go on to contend with all other waiters for |
| 152 | * the mutex. Auf in den Kampf! |
| 153 | */ |
| 154 | } |
| 155 | /* lock external mutex again */ |
| 156 | EnterCriticalSection(mutex); |
| 157 | |
| 158 | return 0; |
| 159 | } |
| 160 | |
| 161 | /* |
| 162 | * IMPORTANT: This implementation requires that pthread_cond_signal |
no outgoing calls
no test coverage detected
searching dependent graphs…