| 146 | } |
| 147 | |
| 148 | apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t *queue_info, |
| 149 | int *had_to_block) |
| 150 | { |
| 151 | apr_status_t rv; |
| 152 | |
| 153 | /* Block if there isn't any idle worker. |
| 154 | * apr_atomic_add32(x, -1) does the same as dec32(x), except |
| 155 | * that it returns the previous value (unlike dec32's bool). |
| 156 | */ |
| 157 | if (apr_atomic_add32(&queue_info->idlers, -1) <= zero_pt) { |
| 158 | rv = apr_thread_mutex_lock(queue_info->idlers_mutex); |
| 159 | if (rv != APR_SUCCESS) { |
| 160 | AP_DEBUG_ASSERT(0); |
| 161 | apr_atomic_inc32(&(queue_info->idlers)); /* back out dec */ |
| 162 | return rv; |
| 163 | } |
| 164 | /* Re-check the idle worker count to guard against a |
| 165 | * race condition. Now that we're in the mutex-protected |
| 166 | * region, one of two things may have happened: |
| 167 | * - If the idle worker count is still negative, the |
| 168 | * workers are all still busy, so it's safe to |
| 169 | * block on a condition variable. |
| 170 | * - If the idle worker count is non-negative, then a |
| 171 | * worker has become idle since the first check |
| 172 | * of queue_info->idlers above. It's possible |
| 173 | * that the worker has also signaled the condition |
| 174 | * variable--and if so, the listener missed it |
| 175 | * because it wasn't yet blocked on the condition |
| 176 | * variable. But if the idle worker count is |
| 177 | * now non-negative, it's safe for this function to |
| 178 | * return immediately. |
| 179 | * |
| 180 | * A "negative value" (relative to zero_pt) in |
| 181 | * queue_info->idlers tells how many |
| 182 | * threads are waiting on an idle worker. |
| 183 | */ |
| 184 | if (queue_info->idlers < zero_pt) { |
| 185 | if (had_to_block) { |
| 186 | *had_to_block = 1; |
| 187 | } |
| 188 | rv = apr_thread_cond_wait(queue_info->wait_for_idler, |
| 189 | queue_info->idlers_mutex); |
| 190 | if (rv != APR_SUCCESS) { |
| 191 | AP_DEBUG_ASSERT(0); |
| 192 | apr_thread_mutex_unlock(queue_info->idlers_mutex); |
| 193 | return rv; |
| 194 | } |
| 195 | } |
| 196 | rv = apr_thread_mutex_unlock(queue_info->idlers_mutex); |
| 197 | if (rv != APR_SUCCESS) { |
| 198 | return rv; |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | if (queue_info->terminated) { |
| 203 | return APR_EOF; |
| 204 | } |
| 205 | else { |
no outgoing calls
no test coverage detected