| 215 | } |
| 216 | |
| 217 | void ap_queue_info_push_pool(fd_queue_info_t *queue_info, |
| 218 | apr_pool_t *pool_to_recycle) |
| 219 | { |
| 220 | struct recycled_pool *new_recycle; |
| 221 | /* If we have been given a pool to recycle, atomically link |
| 222 | * it into the queue_info's list of recycled pools |
| 223 | */ |
| 224 | if (!pool_to_recycle) |
| 225 | return; |
| 226 | |
| 227 | if (queue_info->max_recycled_pools >= 0) { |
| 228 | apr_uint32_t n = apr_atomic_read32(&queue_info->recycled_pools_count); |
| 229 | if (n >= queue_info->max_recycled_pools) { |
| 230 | apr_pool_destroy(pool_to_recycle); |
| 231 | return; |
| 232 | } |
| 233 | apr_atomic_inc32(&queue_info->recycled_pools_count); |
| 234 | } |
| 235 | |
| 236 | apr_pool_clear(pool_to_recycle); |
| 237 | new_recycle = apr_palloc(pool_to_recycle, sizeof *new_recycle); |
| 238 | new_recycle->pool = pool_to_recycle; |
| 239 | for (;;) { |
| 240 | /* |
| 241 | * Save queue_info->recycled_pool in local variable next because |
| 242 | * new_recycle->next can be changed after apr_atomic_casptr |
| 243 | * function call. For gory details see PR 44402. |
| 244 | */ |
| 245 | struct recycled_pool *next = queue_info->recycled_pools; |
| 246 | new_recycle->next = next; |
| 247 | if (apr_atomic_casptr((void *)&queue_info->recycled_pools, |
| 248 | new_recycle, next) == next) |
| 249 | break; |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | void ap_queue_info_pop_pool(fd_queue_info_t *queue_info, |
| 254 | apr_pool_t **recycled_pool) |
no outgoing calls
no test coverage detected