mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-12-24 19:11:00 +01:00
The locking in the dequeuing process was significantly improved by commit
49667c14b ("MEDIUM: queue: take the proxy lock only during the px queue
accesses") in that it tries hard to limit the time during which the
proxy's queue lock is held to the strict minimum. Unfortunately it's not
enough anymore, because we take up the task and manipulate a few pendconn
elements after releasing the proxy's lock (while we're under the server's
lock) but the task will not necessarily hold the server lock since it may
not have successfully found one (e.g. timeout in the backend queue). As
such, stream_free() calling pendconn_free() may release the pendconn
immediately after the proxy's lock is released while the other thread
currently proceeding with the dequeuing tries to wake up the owner's
task and dies in task_wakeup().
One solution consists in releasing le proxy's lock later. But tests have
shown that we'd have to sacrifice a significant share of the performance
gained with the patch above (roughly a 20% loss).
This patch takes another approach. It adds a "del_lock" to each pendconn
struct, that allows to keep it referenced while the proxy's lock is being
released. It's mostly a serialization lock like a refcount, just to maintain
the pendconn alive till the task_wakeup() call is complete. This way we can
continue to release the proxy's lock early while keeping this one. It had
to be added to the few points where we're about to free a pendconn, namely
in pendconn_dequeue() and pendconn_unlink(). This way we continue to
release the proxy's lock very early and there is no performance degradation.
This lock may only be held under the queue's lock to prevent lock
inversion.
No backport is needed since the patch above was merged in 2.5-dev only.
60 lines
2.0 KiB
C
60 lines
2.0 KiB
C
/*
|
|
* include/haproxy/queue-t.h
|
|
* This file defines variables and structures needed for queues.
|
|
*
|
|
* Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
* exclusively.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef _HAPROXY_QUEUE_T_H
|
|
#define _HAPROXY_QUEUE_T_H
|
|
|
|
#include <import/eb32tree.h>
|
|
#include <haproxy/api-t.h>
|
|
|
|
struct proxy;
|
|
struct server;
|
|
struct stream;
|
|
struct queue;
|
|
|
|
struct pendconn {
|
|
int strm_flags; /* stream flags */
|
|
unsigned int queue_idx; /* value of proxy/server queue_idx at time of enqueue */
|
|
struct stream *strm;
|
|
struct queue *queue; /* the queue the entry is queued into */
|
|
struct server *target; /* the server that was assigned, = srv except if srv==NULL */
|
|
struct eb32_node node;
|
|
__decl_thread(HA_SPINLOCK_T del_lock); /* use before removal, always under queue's lock */
|
|
};
|
|
|
|
struct queue {
|
|
struct eb_root head; /* queued pendconnds */
|
|
struct proxy *px; /* the proxy we're waiting for, never NULL in queue */
|
|
struct server *sv; /* the server we are waiting for, may be NULL if don't care */
|
|
__decl_thread(HA_SPINLOCK_T lock); /* for manipulations in the tree */
|
|
unsigned int idx; /* current queuing index */
|
|
unsigned int length; /* number of entries */
|
|
};
|
|
|
|
#endif /* _HAPROXY_QUEUE_T_H */
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*/
|