From ac66d6bafbda79946e25aed6657f4ceab3e39536 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 20 Oct 2020 17:24:27 +0200 Subject: [PATCH] MINOR: proxy; replace the spinlock with an rwlock This is an anticipation of finer grained locking for the queues. For now all lock places take a write lock so that there is no difference at all with previous code. --- include/haproxy/proxy-t.h | 2 +- src/haproxy.c | 2 +- src/listener.c | 4 ++-- src/proxy.c | 40 +++++++++++++++++++-------------------- src/queue.c | 12 ++++++------ src/server.c | 4 ++-- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index 1e59373c9..41aca9d39 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -321,7 +321,7 @@ struct proxy { int clientfin; /* timeout to apply to client half-closed connections */ int serverfin; /* timeout to apply to server half-closed connections */ } timeout; - __decl_thread(HA_SPINLOCK_T lock); /* may be taken under the server's lock */ + __decl_thread(HA_RWLOCK_T lock); /* may be taken under the server's lock */ char *id, *desc; /* proxy id (name) and description */ struct eb_root pendconns; /* pending connections with no server assigned yet */ diff --git a/src/haproxy.c b/src/haproxy.c index cc5cc1aea..3e6fd18f7 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2697,7 +2697,7 @@ void deinit(void) p0 = p; p = p->next; HA_RWLOCK_DESTROY(&p0->lbprm.lock); - HA_SPIN_DESTROY(&p0->lock); + HA_RWLOCK_DESTROY(&p0->lock); free(p0); }/* end while(p) */ diff --git a/src/listener.c b/src/listener.c index 7061f9a9d..1947fdb53 100644 --- a/src/listener.c +++ b/src/listener.c @@ -295,7 +295,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli) } if (!lpx) - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); if (!lpr) HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); @@ -319,7 +319,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli) HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); if (!lpx) - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); } /* default function called to suspend a listener: it simply passes the call to diff --git a/src/proxy.c b/src/proxy.c index 790d4d080..fa17eebb6 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1041,7 +1041,7 @@ void init_new_proxy(struct proxy *p) /* Default to only allow L4 retries */ p->retry_type = PR_RE_CONN_FAILED; - HA_SPIN_INIT(&p->lock); + HA_RWLOCK_INIT(&p->lock); } /* to be called under the proxy lock after stopping some listeners. This will @@ -1310,7 +1310,7 @@ void stop_proxy(struct proxy *p) { struct listener *l; - HA_SPIN_LOCK(PROXY_LOCK, &p->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock); list_for_each_entry(l, &p->conf.listeners, by_fe) stop_listener(l, 1, 0, 0); @@ -1320,7 +1320,7 @@ void stop_proxy(struct proxy *p) p->disabled = 1; } - HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock); } /* This function resumes listening on the specified proxy. It scans all of its @@ -1559,14 +1559,14 @@ void proxy_capture_error(struct proxy *proxy, int is_back, /* note: we still lock since we have to be certain that nobody is * dumping the output while we free. */ - HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &proxy->lock); if (is_back) { es = HA_ATOMIC_XCHG(&proxy->invalid_rep, es); } else { es = HA_ATOMIC_XCHG(&proxy->invalid_req, es); } free(es); - HA_SPIN_UNLOCK(PROXY_LOCK, &proxy->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &proxy->lock); } /* Configure all proxies which lack a maxconn setting to use the global one by @@ -1936,9 +1936,9 @@ static int cli_parse_enable_dyncookie_backend(char **args, char *payload, struct /* Note: this lock is to make sure this doesn't change while another * thread is in srv_set_dyncookie(). */ - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); px->ck_opts |= PR_CK_DYNAMIC; - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); for (s = px->srv; s != NULL; s = s->next) { HA_SPIN_LOCK(SERVER_LOCK, &s->lock); @@ -1968,9 +1968,9 @@ static int cli_parse_disable_dyncookie_backend(char **args, char *payload, struc /* Note: this lock is to make sure this doesn't change while another * thread is in srv_set_dyncookie(). */ - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); px->ck_opts &= ~PR_CK_DYNAMIC; - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); for (s = px->srv; s != NULL; s = s->next) { HA_SPIN_LOCK(SERVER_LOCK, &s->lock); @@ -2011,10 +2011,10 @@ static int cli_parse_set_dyncookie_key_backend(char **args, char *payload, struc /* Note: this lock is to make sure this doesn't change while another * thread is in srv_set_dyncookie(). */ - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); free(px->dyncookie_key); px->dyncookie_key = newkey; - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); for (s = px->srv; s != NULL; s = s->next) { HA_SPIN_LOCK(SERVER_LOCK, &s->lock); @@ -2052,7 +2052,7 @@ static int cli_parse_set_maxconn_frontend(char **args, char *payload, struct app /* OK, the value is fine, so we assign it to the proxy and to all of * its listeners. The blocked ones will be dequeued. */ - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); px->maxconn = v; list_for_each_entry(l, &px->conf.listeners, by_fe) { @@ -2063,7 +2063,7 @@ static int cli_parse_set_maxconn_frontend(char **args, char *payload, struct app if (px->maxconn > px->feconn) dequeue_proxy_listeners(px); - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); return 1; } @@ -2112,9 +2112,9 @@ static int cli_parse_disable_frontend(char **args, char *payload, struct appctx if (!px->li_ready) return cli_msg(appctx, LOG_NOTICE, "All sockets are already disabled.\n"); - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); ret = pause_proxy(px); - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); if (!ret) return cli_err(appctx, "Failed to pause frontend, check logs for precise cause.\n"); @@ -2144,9 +2144,9 @@ static int cli_parse_enable_frontend(char **args, char *payload, struct appctx * if (px->li_ready == px->li_all) return cli_msg(appctx, LOG_NOTICE, "All sockets are already enabled.\n"); - HA_SPIN_LOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); ret = resume_proxy(px); - HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); if (!ret) return cli_err(appctx, "Failed to resume frontend, check logs for precise cause (port conflict?).\n"); @@ -2225,7 +2225,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx) while (appctx->ctx.errors.px) { struct error_snapshot *es; - HA_SPIN_LOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); if ((appctx->ctx.errors.flag & 1) == 0) { es = appctx->ctx.errors.px->invalid_req; @@ -2335,7 +2335,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx) appctx->ctx.errors.bol = newline; }; next: - HA_SPIN_UNLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); appctx->ctx.errors.bol = 0; appctx->ctx.errors.ptr = -1; appctx->ctx.errors.flag ^= 1; @@ -2347,7 +2347,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx) return 1; cant_send_unlock: - HA_SPIN_UNLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); cant_send: si_rx_room_blk(si); return 0; diff --git a/src/queue.c b/src/queue.c index 312c91fca..f571878de 100644 --- a/src/queue.c +++ b/src/queue.c @@ -152,7 +152,7 @@ static inline void pendconn_queue_lock(struct pendconn *p) if (p->srv) HA_SPIN_LOCK(SERVER_LOCK, &p->srv->lock); else - HA_SPIN_LOCK(PROXY_LOCK, &p->px->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->px->lock); } /* Unlocks the queue the pendconn element belongs to. This relies on both p->px @@ -164,7 +164,7 @@ static inline void pendconn_queue_unlock(struct pendconn *p) if (p->srv) HA_SPIN_UNLOCK(SERVER_LOCK, &p->srv->lock); else - HA_SPIN_UNLOCK(PROXY_LOCK, &p->px->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->px->lock); } /* Removes the pendconn from the server/proxy queue. At this stage, the @@ -312,14 +312,14 @@ void process_srv_queue(struct server *s) int maxconn; HA_SPIN_LOCK(SERVER_LOCK, &s->lock); - HA_SPIN_LOCK(PROXY_LOCK, &p->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock); maxconn = srv_dynamic_maxconn(s); while (s->served < maxconn) { int ret = pendconn_process_next_strm(s, p); if (!ret) break; } - HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock); HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock); } @@ -444,7 +444,7 @@ int pendconn_grab_from_px(struct server *s) ((s != s->proxy->lbprm.fbck) && !(s->proxy->options & PR_O_USE_ALL_BK)))) return 0; - HA_SPIN_LOCK(PROXY_LOCK, &s->proxy->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &s->proxy->lock); maxconn = srv_dynamic_maxconn(s); while ((p = pendconn_first(&s->proxy->pendconns))) { if (s->maxconn && s->served + xferred >= maxconn) @@ -456,7 +456,7 @@ int pendconn_grab_from_px(struct server *s) task_wakeup(p->strm->task, TASK_WOKEN_RES); xferred++; } - HA_SPIN_UNLOCK(PROXY_LOCK, &s->proxy->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &s->proxy->lock); return xferred; } diff --git a/src/server.c b/src/server.c index 2271f9e99..cdb5bce68 100644 --- a/src/server.c +++ b/src/server.c @@ -139,7 +139,7 @@ void srv_set_dyncookie(struct server *s) int addr_len; int port; - HA_SPIN_LOCK(PROXY_LOCK, &p->lock); + HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock); if ((s->flags & SRV_F_COOKIESET) || !(s->proxy->ck_opts & PR_CK_DYNAMIC) || @@ -188,7 +188,7 @@ void srv_set_dyncookie(struct server *s) if (!(s->next_admin & SRV_ADMF_FMAINT)) srv_check_for_dup_dyncookie(s); out: - HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock); + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock); } /*