| 251 | } |
| 252 | |
| 253 | void ap_queue_info_pop_pool(fd_queue_info_t *queue_info, |
| 254 | apr_pool_t **recycled_pool) |
| 255 | { |
| 256 | /* Atomically pop a pool from the recycled list */ |
| 257 | |
| 258 | /* This function is safe only as long as it is single threaded because |
| 259 | * it reaches into the queue and accesses "next" which can change. |
| 260 | * We are OK today because it is only called from the listener thread. |
| 261 | * cas-based pushes do not have the same limitation - any number can |
| 262 | * happen concurrently with a single cas-based pop. |
| 263 | */ |
| 264 | |
| 265 | *recycled_pool = NULL; |
| 266 | |
| 267 | |
| 268 | /* Atomically pop a pool from the recycled list */ |
| 269 | for (;;) { |
| 270 | struct recycled_pool *first_pool = queue_info->recycled_pools; |
| 271 | if (first_pool == NULL) { |
| 272 | break; |
| 273 | } |
| 274 | if (apr_atomic_casptr((void *)&queue_info->recycled_pools, |
| 275 | first_pool->next, first_pool) == first_pool) { |
| 276 | *recycled_pool = first_pool->pool; |
| 277 | if (queue_info->max_recycled_pools >= 0) |
| 278 | apr_atomic_dec32(&queue_info->recycled_pools_count); |
| 279 | break; |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | void ap_queue_info_free_idle_pools(fd_queue_info_t *queue_info) |
| 285 | { |
no outgoing calls
no test coverage detected