mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-27 13:28:32 +00:00
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.
This commit is contained in:
parent
de785f04e1
commit
ac66d6bafb
@ -321,7 +321,7 @@ struct proxy {
|
|||||||
int clientfin; /* timeout to apply to client half-closed connections */
|
int clientfin; /* timeout to apply to client half-closed connections */
|
||||||
int serverfin; /* timeout to apply to server half-closed connections */
|
int serverfin; /* timeout to apply to server half-closed connections */
|
||||||
} timeout;
|
} 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 */
|
char *id, *desc; /* proxy id (name) and description */
|
||||||
struct eb_root pendconns; /* pending connections with no server assigned yet */
|
struct eb_root pendconns; /* pending connections with no server assigned yet */
|
||||||
|
@ -2697,7 +2697,7 @@ void deinit(void)
|
|||||||
p0 = p;
|
p0 = p;
|
||||||
p = p->next;
|
p = p->next;
|
||||||
HA_RWLOCK_DESTROY(&p0->lbprm.lock);
|
HA_RWLOCK_DESTROY(&p0->lbprm.lock);
|
||||||
HA_SPIN_DESTROY(&p0->lock);
|
HA_RWLOCK_DESTROY(&p0->lock);
|
||||||
free(p0);
|
free(p0);
|
||||||
}/* end while(p) */
|
}/* end while(p) */
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!lpx)
|
if (!lpx)
|
||||||
HA_SPIN_LOCK(PROXY_LOCK, &px->lock);
|
HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock);
|
||||||
|
|
||||||
if (!lpr)
|
if (!lpr)
|
||||||
HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
|
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);
|
HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
|
||||||
|
|
||||||
if (!lpx)
|
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
|
/* default function called to suspend a listener: it simply passes the call to
|
||||||
|
40
src/proxy.c
40
src/proxy.c
@ -1041,7 +1041,7 @@ void init_new_proxy(struct proxy *p)
|
|||||||
/* Default to only allow L4 retries */
|
/* Default to only allow L4 retries */
|
||||||
p->retry_type = PR_RE_CONN_FAILED;
|
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
|
/* 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;
|
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)
|
list_for_each_entry(l, &p->conf.listeners, by_fe)
|
||||||
stop_listener(l, 1, 0, 0);
|
stop_listener(l, 1, 0, 0);
|
||||||
@ -1320,7 +1320,7 @@ void stop_proxy(struct proxy *p)
|
|||||||
p->disabled = 1;
|
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
|
/* 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
|
/* note: we still lock since we have to be certain that nobody is
|
||||||
* dumping the output while we free.
|
* dumping the output while we free.
|
||||||
*/
|
*/
|
||||||
HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock);
|
HA_RWLOCK_WRLOCK(PROXY_LOCK, &proxy->lock);
|
||||||
if (is_back) {
|
if (is_back) {
|
||||||
es = HA_ATOMIC_XCHG(&proxy->invalid_rep, es);
|
es = HA_ATOMIC_XCHG(&proxy->invalid_rep, es);
|
||||||
} else {
|
} else {
|
||||||
es = HA_ATOMIC_XCHG(&proxy->invalid_req, es);
|
es = HA_ATOMIC_XCHG(&proxy->invalid_req, es);
|
||||||
}
|
}
|
||||||
free(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
|
/* 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
|
/* Note: this lock is to make sure this doesn't change while another
|
||||||
* thread is in srv_set_dyncookie().
|
* 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;
|
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) {
|
for (s = px->srv; s != NULL; s = s->next) {
|
||||||
HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
|
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
|
/* Note: this lock is to make sure this doesn't change while another
|
||||||
* thread is in srv_set_dyncookie().
|
* 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;
|
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) {
|
for (s = px->srv; s != NULL; s = s->next) {
|
||||||
HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
|
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
|
/* Note: this lock is to make sure this doesn't change while another
|
||||||
* thread is in srv_set_dyncookie().
|
* thread is in srv_set_dyncookie().
|
||||||
*/
|
*/
|
||||||
HA_SPIN_LOCK(PROXY_LOCK, &px->lock);
|
HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock);
|
||||||
free(px->dyncookie_key);
|
free(px->dyncookie_key);
|
||||||
px->dyncookie_key = newkey;
|
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) {
|
for (s = px->srv; s != NULL; s = s->next) {
|
||||||
HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
|
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
|
/* OK, the value is fine, so we assign it to the proxy and to all of
|
||||||
* its listeners. The blocked ones will be dequeued.
|
* 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;
|
px->maxconn = v;
|
||||||
list_for_each_entry(l, &px->conf.listeners, by_fe) {
|
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)
|
if (px->maxconn > px->feconn)
|
||||||
dequeue_proxy_listeners(px);
|
dequeue_proxy_listeners(px);
|
||||||
|
|
||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2112,9 +2112,9 @@ static int cli_parse_disable_frontend(char **args, char *payload, struct appctx
|
|||||||
if (!px->li_ready)
|
if (!px->li_ready)
|
||||||
return cli_msg(appctx, LOG_NOTICE, "All sockets are already disabled.\n");
|
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);
|
ret = pause_proxy(px);
|
||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return cli_err(appctx, "Failed to pause frontend, check logs for precise cause.\n");
|
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)
|
if (px->li_ready == px->li_all)
|
||||||
return cli_msg(appctx, LOG_NOTICE, "All sockets are already enabled.\n");
|
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);
|
ret = resume_proxy(px);
|
||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return cli_err(appctx, "Failed to resume frontend, check logs for precise cause (port conflict?).\n");
|
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) {
|
while (appctx->ctx.errors.px) {
|
||||||
struct error_snapshot *es;
|
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) {
|
if ((appctx->ctx.errors.flag & 1) == 0) {
|
||||||
es = appctx->ctx.errors.px->invalid_req;
|
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;
|
appctx->ctx.errors.bol = newline;
|
||||||
};
|
};
|
||||||
next:
|
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.bol = 0;
|
||||||
appctx->ctx.errors.ptr = -1;
|
appctx->ctx.errors.ptr = -1;
|
||||||
appctx->ctx.errors.flag ^= 1;
|
appctx->ctx.errors.flag ^= 1;
|
||||||
@ -2347,7 +2347,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
cant_send_unlock:
|
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:
|
cant_send:
|
||||||
si_rx_room_blk(si);
|
si_rx_room_blk(si);
|
||||||
return 0;
|
return 0;
|
||||||
|
12
src/queue.c
12
src/queue.c
@ -152,7 +152,7 @@ static inline void pendconn_queue_lock(struct pendconn *p)
|
|||||||
if (p->srv)
|
if (p->srv)
|
||||||
HA_SPIN_LOCK(SERVER_LOCK, &p->srv->lock);
|
HA_SPIN_LOCK(SERVER_LOCK, &p->srv->lock);
|
||||||
else
|
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
|
/* 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)
|
if (p->srv)
|
||||||
HA_SPIN_UNLOCK(SERVER_LOCK, &p->srv->lock);
|
HA_SPIN_UNLOCK(SERVER_LOCK, &p->srv->lock);
|
||||||
else
|
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
|
/* 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;
|
int maxconn;
|
||||||
|
|
||||||
HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
|
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);
|
maxconn = srv_dynamic_maxconn(s);
|
||||||
while (s->served < maxconn) {
|
while (s->served < maxconn) {
|
||||||
int ret = pendconn_process_next_strm(s, p);
|
int ret = pendconn_process_next_strm(s, p);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock);
|
||||||
HA_SPIN_UNLOCK(SERVER_LOCK, &s->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))))
|
((s != s->proxy->lbprm.fbck) && !(s->proxy->options & PR_O_USE_ALL_BK))))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
HA_SPIN_LOCK(PROXY_LOCK, &s->proxy->lock);
|
HA_RWLOCK_WRLOCK(PROXY_LOCK, &s->proxy->lock);
|
||||||
maxconn = srv_dynamic_maxconn(s);
|
maxconn = srv_dynamic_maxconn(s);
|
||||||
while ((p = pendconn_first(&s->proxy->pendconns))) {
|
while ((p = pendconn_first(&s->proxy->pendconns))) {
|
||||||
if (s->maxconn && s->served + xferred >= maxconn)
|
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);
|
task_wakeup(p->strm->task, TASK_WOKEN_RES);
|
||||||
xferred++;
|
xferred++;
|
||||||
}
|
}
|
||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &s->proxy->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &s->proxy->lock);
|
||||||
return xferred;
|
return xferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ void srv_set_dyncookie(struct server *s)
|
|||||||
int addr_len;
|
int addr_len;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
HA_SPIN_LOCK(PROXY_LOCK, &p->lock);
|
HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock);
|
||||||
|
|
||||||
if ((s->flags & SRV_F_COOKIESET) ||
|
if ((s->flags & SRV_F_COOKIESET) ||
|
||||||
!(s->proxy->ck_opts & PR_CK_DYNAMIC) ||
|
!(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))
|
if (!(s->next_admin & SRV_ADMF_FMAINT))
|
||||||
srv_check_for_dup_dyncookie(s);
|
srv_check_for_dup_dyncookie(s);
|
||||||
out:
|
out:
|
||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user