]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: listener: replace the listener's spinlock with an rwlock
authorWilly Tarreau <w@1wt.eu>
Tue, 1 Feb 2022 15:23:00 +0000 (16:23 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 1 Feb 2022 15:51:55 +0000 (16:51 +0100)
We'll need to lock the listener a little bit more during accept() and
tests show that a spinlock is a massive performance killer, so let's
first switch to an rwlock for this lock.

This patch might have to be backported for the next patch to work, and
if so, the change is almost mechanical (look for LISTENER_LOCK), but do
not forget about the few HA_SPIN_INIT() in the file. There's no reference
to this lock outside of listener.c nor listener-t.h.

include/haproxy/listener-t.h
src/listener.c

index c173abff436ba57a559706183a3253f6dccf5ae0..5d2093a805dcb251b55d22e45d4b0ed1a281915f 100644 (file)
@@ -214,7 +214,7 @@ struct listener {
        int luid;                       /* listener universally unique ID, used for SNMP */
        int options;                    /* socket options : LI_O_* */
        int flags;                      /* LI_F_* flags */
-       __decl_thread(HA_SPINLOCK_T lock);
+       __decl_thread(HA_RWLOCK_T lock);
 
        struct fe_counters *counters;   /* statistics counters */
        int nbconn;                     /* current number of connections on this listener */
index db505cdc6943876a9e23007b483ffb5657a08cf6..07486acde15beb0e51a81e8c57f6d9a2125df9da 100644 (file)
@@ -288,7 +288,7 @@ void listener_set_state(struct listener *l, enum li_state st)
  */
 void enable_listener(struct listener *listener)
 {
-       HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &listener->lock);
 
        /* If this listener is supposed to be only in the master, close it in
         * the workers. Conversely, if it's supposed to be only in the workers
@@ -315,7 +315,7 @@ void enable_listener(struct listener *listener)
                }
        }
 
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &listener->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &listener->lock);
 }
 
 /*
@@ -344,7 +344,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
                HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
 
        if (!lli)
-               HA_SPIN_LOCK(LISTENER_LOCK, &l->lock);
+               HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
 
        if (l->state > LI_INIT) {
                do_unbind_listener(l);
@@ -356,7 +356,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
        }
 
        if (!lli)
-               HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock);
+               HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
 
        if (!lpr)
                HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
@@ -451,7 +451,7 @@ int pause_listener(struct listener *l)
        struct proxy *px = l->bind_conf->frontend;
        int ret = 1;
 
-       HA_SPIN_LOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
 
        if (l->state <= LI_PAUSED)
                goto end;
@@ -468,7 +468,7 @@ int pause_listener(struct listener *l)
                send_log(px, LOG_WARNING, "Paused %s %s.\n", proxy_cap_str(px->cap), px->id);
        }
   end:
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
        return ret;
 }
 
@@ -488,7 +488,7 @@ int resume_listener(struct listener *l)
        int was_paused = px && px->li_paused;
        int ret = 1;
 
-       HA_SPIN_LOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
 
        /* check that another thread didn't to the job in parallel (e.g. at the
         * end of listen_accept() while we'd come from dequeue_all_listeners().
@@ -517,7 +517,7 @@ int resume_listener(struct listener *l)
                send_log(px, LOG_WARNING, "Resumed %s %s.\n", proxy_cap_str(px->cap), px->id);
        }
   end:
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
        return ret;
 }
 
@@ -526,7 +526,7 @@ int resume_listener(struct listener *l)
  */
 static void listener_full(struct listener *l)
 {
-       HA_SPIN_LOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
        if (l->state >= LI_READY) {
                MT_LIST_DELETE(&l->wait_queue);
                if (l->state != LI_FULL) {
@@ -534,7 +534,7 @@ static void listener_full(struct listener *l)
                        listener_set_state(l, LI_FULL);
                }
        }
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
 }
 
 /* Marks a ready listener as limited so that we only try to re-enable it when
@@ -542,13 +542,13 @@ static void listener_full(struct listener *l)
  */
 static void limit_listener(struct listener *l, struct mt_list *list)
 {
-       HA_SPIN_LOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
        if (l->state == LI_READY) {
                MT_LIST_TRY_APPEND(list, &l->wait_queue);
                l->rx.proto->disable(l);
                listener_set_state(l, LI_LIMITED);
        }
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
 }
 
 /* Dequeues all listeners waiting for a resource the global wait queue */
@@ -630,9 +630,9 @@ void do_unbind_listener(struct listener *listener)
  */
 void unbind_listener(struct listener *listener)
 {
-       HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &listener->lock);
        do_unbind_listener(listener);
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &listener->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &listener->lock);
 }
 
 /* creates one or multiple listeners for bind_conf <bc> on sockaddr <ss> on port
@@ -678,7 +678,7 @@ int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
 
                l->extra_counters = NULL;
 
-               HA_SPIN_INIT(&l->lock);
+               HA_RWLOCK_INIT(&l->lock);
                _HA_ATOMIC_INC(&jobs);
                _HA_ATOMIC_INC(&listeners);
        }
@@ -720,7 +720,7 @@ struct listener *clone_listener(struct listener *src)
 
        l->rx.proto->add(l->rx.proto, l);
 
-       HA_SPIN_INIT(&l->lock);
+       HA_RWLOCK_INIT(&l->lock);
        _HA_ATOMIC_INC(&jobs);
        _HA_ATOMIC_INC(&listeners);
        global.maxsock++;
@@ -757,9 +757,9 @@ void __delete_listener(struct listener *listener)
 void delete_listener(struct listener *listener)
 {
        HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
-       HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock);
+       HA_RWLOCK_WRLOCK(LISTENER_LOCK, &listener->lock);
        __delete_listener(listener);
-       HA_SPIN_UNLOCK(LISTENER_LOCK, &listener->lock);
+       HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &listener->lock);
        HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
 }