static void
ngx_http_limit_conn_cleanup(void *data)
{
    ngx_http_limit_conn_cleanup_t  *lccln = data;
    ngx_slab_pool_t             *shpool;
    ngx_rbtree_node_t           *node;
    ngx_http_limit_conn_ctx_t   *ctx;
    ngx_http_limit_conn_node_t  *lc;
    ctx = lccln->shm_zone->data;
    shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
    node = lccln->node;
    lc = (ngx_http_limit_conn_node_t *) &node->color;
    ngx_shmtx_lock(&shpool->mutex);
    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
                   "limit conn cleanup: %08XD %d", node->key, lc->conn);
    lc->conn--;
    if (lc->conn == 0) {
        ngx_rbtree_delete(ctx->rbtree, node);
        ngx_slab_free_locked(shpool, node);
    }
    ngx_shmtx_unlock(&shpool->mutex);
}
['static void\nngx_http_limit_conn_cleanup(void *data)\n{\n    ngx_http_limit_conn_cleanup_t  *lccln = data;\n    ngx_slab_pool_t             *shpool;\n    ngx_rbtree_node_t           *node;\n    ngx_http_limit_conn_ctx_t   *ctx;\n    ngx_http_limit_conn_node_t  *lc;\n    ctx = lccln->shm_zone->data;\n    shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;\n    node = lccln->node;\n    lc = (ngx_http_limit_conn_node_t *) &node->color;\n    ngx_shmtx_lock(&shpool->mutex);\n    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,\n                   "limit conn cleanup: %08XD %d", node->key, lc->conn);\n    lc->conn--;\n    if (lc->conn == 0) {\n        ngx_rbtree_delete(ctx->rbtree, node);\n        ngx_slab_free_locked(shpool, node);\n    }\n    ngx_shmtx_unlock(&shpool->mutex);\n}', 'void\nngx_shmtx_lock(ngx_shmtx_t *mtx)\n{\n    ngx_uint_t         i, n;\n    ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");\n    for ( ;; ) {\n        if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {\n            return;\n        }\n        if (ngx_ncpu > 1) {\n            for (n = 1; n < mtx->spin; n <<= 1) {\n                for (i = 0; i < n; i++) {\n                    ngx_cpu_pause();\n                }\n                if (*mtx->lock == 0\n                    && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))\n                {\n                    return;\n                }\n            }\n        }\n#if (NGX_HAVE_POSIX_SEM)\n        if (mtx->semaphore) {\n            (void) ngx_atomic_fetch_add(mtx->wait, 1);\n            if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {\n                return;\n            }\n            ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,\n                           "shmtx wait %uA", *mtx->wait);\n            while (sem_wait(&mtx->sem) == -1) {\n                ngx_err_t  err;\n                err = ngx_errno;\n                if (err != NGX_EINTR) {\n                    ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,\n                                  "sem_wait() failed while waiting on shmtx");\n                    break;\n                }\n                ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,\n                               "shmtx awoke");\n            }\n            continue;\n        }\n#endif\n        ngx_sched_yield();\n    }\n}']