haproxy/include/haproxy/queue-t.h

61 lines
2 KiB
C
Raw Normal View History

/*
* 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/ebtree-t.h>
#include <haproxy/api-t.h>
#include <haproxy/thread-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;
BUG/MAJOR: queue: better protect a pendconn being picked from the proxy 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.
2021-08-31 11:21:39 -04:00
__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:
*/